Что самый легкий путь состоит в том, чтобы зашифровать пароль, когда я сохраняю его к реестру?

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

58
задан John Saunders 14 April 2012 в 17:15
поделиться

10 ответов

Вы не дешифруете пароли аутентификации!

Хешируют их использующий что-то как поставщик SHA256 и когда необходимо бросить вызов, хешировать вход от пользователя и видеть, соответствуют ли два хеша.

byte[] data = System.Text.Encoding.ASCII.GetBytes(inputString);
data = new System.Security.Cryptography.SHA256Managed().ComputeHash(data);
String hash = System.Text.Encoding.ASCII.GetString(data);

обратимые пароли Отъезда действительно ужасная модель.

Edit2: Я думал, что мы просто говорили о пограничной аутентификации. Уверенный существуют случаи, где Вы хотите зашифровать пароли для других вещей, которые должны быть обратимыми, но должна быть блокировка с 1 путем сверху всего этого (за очень немногими исключениями).

я обновил алгоритм хеширования, но для самой лучшей силы Вы хотите оставаться частная соль и добавить это к Вашему входу прежде хеширование его . Вы сделали бы это снова, когда Вы выдерживаете сравнение. Это добавляет другой слой, делающий его еще тяжелее для кого-то для инвертирования.

125
ответ дан Community 24 November 2019 в 18:38
поделиться

Также рассмотрите "соление" Вашего хеша (не кулинарное понятие!). В основном это означает добавлять некоторый случайный текст к паролю перед хешированием его.

" соленое значение помогает замедлиться, взломщик работают, атака с подбором по словарю должна Ваше учетное хранилище поставиться под угрозу, давая Вам дополнительное время, чтобы обнаружить и реагировать на компромисс. "

Для хранения хэшей пароля:

a) Генерируют случайное соленое значение:

byte[] salt = new byte[32];
System.Security.Cryptography.RNGCryptoServiceProvider.Create().GetBytes(salt);

b) Добавляют соль к паролю.

// Convert the plain string pwd into bytes
byte[] plainTextBytes = System.Text UnicodeEncoding.Unicode.GetBytes(plainText);
// Append salt to pwd before hashing
byte[] combinedBytes = new byte[plainTextBytes.Length + salt.Length];
System.Buffer.BlockCopy(plainTextBytes, 0, combinedBytes, 0, plainTextBytes.Length);
System.Buffer.BlockCopy(salt, 0, combinedBytes, plainTextBytes.Length, salt.Length);

Хеш c) объединенный пароль & соль:

// Create hash for the pwd+salt
System.Security.Cryptography.HashAlgorithm hashAlgo = new System.Security.Cryptography.SHA256Managed();
byte[] hash = hashAlgo.ComputeHash(combinedBytes);

d) Добавляют соль к результирующему хешу.

// Append the salt to the hash
byte[] hashPlusSalt = new byte[hash.Length + salt.Length];
System.Buffer.BlockCopy(hash, 0, hashPlusSalt, 0, hash.Length);
System.Buffer.BlockCopy(salt, 0, hashPlusSalt, hash.Length, salt.Length);

Хранилище e) результат в Вашем пользователе хранят базу данных.

Этот подход означает, что Вы не должны сохранить соль отдельно и затем повторно вычислить хеш с помощью соленого значения и значения незашифрованного пароля, полученного от пользователя.

Редактирование : Поскольку необработанная вычислительная мощность становится более дешевой и быстрее, значение хеширования - или соление хешей - уменьшилось. у Jeff Atwood есть превосходное обновление 2012 года слишком длинный для повторения в целом здесь, который указывает:

Это (использование соленых хешей) обеспечит иллюзию безопасности больше, чем какая-либо фактическая безопасность. Так как Вам нужны и соль и в выбор хеш-алгоритма генерировать хеш и проверить хеш, маловероятно, что взломщик имел бы один, но не другой. Если Вы были скомпрометированы до такой степени, что у взломщика есть Ваша база данных пароля, разумно принять их или иметь или мочь получить Вашу секретную, скрытую соль.

первое правило безопасности состоит в том, чтобы всегда принимать и планировать худшее. Необходимо ли использовать соль, идеально случайную соль для каждого пользователя? Несомненно, это - определенно хорошая практика, и по крайней мере это позволяет Вам снять неоднозначность двух пользователей, у которых есть тот же пароль. Но в эти дни, одни только соли больше не могут сохранять Вас от человека, готового потратить несколько тысяч долларов на аппаратные средства видеокарты, и если Вы думаете, что они могут, Вы быть в беде.

23
ответ дан DOK 24 November 2019 в 18:38
поделиться

Это - то, что требуется сделать:

OurKey.SetValue("Password", StringEncryptor.EncryptString(textBoxPassword.Text));
OurKey.GetValue("Password", StringEncryptor.DecryptString(textBoxPassword.Text));

можно сделать это с этим следующие классы. Этот класс является универсальным классом, клиентская конечная точка. Это включает МОК различных алгоритмов шифрования с помощью Ninject.

public class StringEncryptor
{
    private static IKernel _kernel;

    static StringEncryptor()
    {
        _kernel = new StandardKernel(new EncryptionModule());
    }

    public static string EncryptString(string plainText)
    {
        return _kernel.Get<IStringEncryptor>().EncryptString(plainText);
    }

    public static string DecryptString(string encryptedText)
    {
        return _kernel.Get<IStringEncryptor>().DecryptString(encryptedText);
    }
}

Этот следующий класс является ninject классом, который позволяет Вам вводить различные алгоритмы:

public class EncryptionModule : StandardModule
{
    public override void Load()
    {
        Bind<IStringEncryptor>().To<TripleDESStringEncryptor>();
    }
}

Это - интерфейс, который любой алгоритм должен реализовать для шифрования/дешифрования строк:

public interface IStringEncryptor
{
    string EncryptString(string plainText);
    string DecryptString(string encryptedText);
}

Это - реализация с помощью алгоритма TripleDES:

public class TripleDESStringEncryptor : IStringEncryptor
{
    private byte[] _key;
    private byte[] _iv;
    private TripleDESCryptoServiceProvider _provider;

    public TripleDESStringEncryptor()
    {
        _key = System.Text.ASCIIEncoding.ASCII.GetBytes("GSYAHAGCBDUUADIADKOPAAAW");
        _iv = System.Text.ASCIIEncoding.ASCII.GetBytes("USAZBGAW");
        _provider = new TripleDESCryptoServiceProvider();
    }

    #region IStringEncryptor Members

    public string EncryptString(string plainText)
    {
        return Transform(plainText, _provider.CreateEncryptor(_key, _iv));
    }

    public string DecryptString(string encryptedText)
    {
        return Transform(encryptedText, _provider.CreateDecryptor(_key, _iv));
    }

    #endregion

    private string Transform(string text, ICryptoTransform transform)
    {
        if (text == null)
        {
            return null;
        }
        using (MemoryStream stream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                byte[] input = Encoding.Default.GetBytes(text);
                cryptoStream.Write(input, 0, input.Length);
                cryptoStream.FlushFinalBlock();

                return Encoding.Default.GetString(stream.ToArray());
            }
        }
    }
}

можно посмотреть мой ролик и загрузить код для этого в: http://www.wrightin.gs/2008/11/how-to-encryptdecrypt-sensitive-column-contents-in-nhibernateactive-record-video.html

12
ответ дан Jamie Wright 24 November 2019 в 18:38
поделиться

Одна опция состояла бы в том, чтобы сохранить хеш (SHA1, MD5) пароля вместо пароля в виде открытого текста, и каждый раз, когда Вы хотите видеть, хорош ли пароль, просто сравните его с тем хешем.

, Если Вы должны защитить устройство хранения данных (например, для пароля, который Вы будете использовать для соединения с сервисом), тогда проблема более сложна.

, Если бы это только для аутентификации, тогда было бы достаточно использовать хеш.

10
ответ дан Bogdan Maxim 24 November 2019 в 18:38
поделиться

Если бы Вы хотите быть в состоянии дешифровать пароль, я думаю, что самый легкий путь состоял бы в том, чтобы использовать DPAPI (пользовательский режим хранилища) для шифрования/дешифрования. Таким образом, Вы не должны играть с ключами шифрования, сохранить их где-нибудь или твердый код их в Вашем коде - в обоих случаях кто-то может обнаружить их путем изучения реестра, пользовательских настроек или использования Отражателя.

Иначе использование хеширует SHA1, или MD5 как другие сказали здесь.

9
ответ дан liggett78 24 November 2019 в 18:38
поделиться

Если это - пароль, используемый для аутентификации Вашим приложением, то хешируйте пароль, как другие предполагают.

при хранении паролей для внешнего ресурса Вы будете часто хотеть быть в состоянии предложить пользователю эти учетные данные и дать ему возможность сохранить их надежно. Windows предоставляет Учетным данным UI (CredUI) с этой целью - существует много образцов, показывающих, как использовать это в.NET, включая этот на MSDN.

5
ответ дан Joe 24 November 2019 в 18:38
поделиться

При необходимости в больше, чем это, например, защищая строку подключения (для соединения с базой данных), проверяет этот статья , поскольку это предоставляет лучшую "возможность" для этого.

ответ Oli также хорош, поскольку он показывает, как можно создать хеш для строки.

1
ответ дан Bogdan Maxim 24 November 2019 в 18:38
поделиться

.. СЕТЬ предоставляет cryptographics услуги в классе, содержавшемся в Системе. Безопасность. Пространство имен криптографии.

0
ответ дан osp70 24 November 2019 в 18:38
поделиться

Вместо того, чтобы шифровать/дешифровать, необходимо передавать пароль через алгоритм хеширования, md5/sha512, или подобные. То, что Вы идеально сделали бы, хешировать пароль и сохранить хеш, тогда когда пароль необходим, Вы хешируете запись и сравниваете записи. Пароль никогда не будет тогда "дешифровываться", просто хешироваться и затем сравниваться.

-1
ответ дан Jeremy B. 24 November 2019 в 18:38
поделиться

Как сказанный ligget78, DPAPI был бы хорошим способом пойти для хранения паролей. Проверьте класс ProtectedData на MSDN, например, использование.

6
ответ дан Beau 24 November 2019 в 18:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: