Подтвердить что ты не робот

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

В настоящее время я пишу это в чистом тексте oops!, это в домашней программе, так что это не так уж плохо, но я бы хотел сделать все правильно. Как следует шифровать это при записи в реестр и как его расшифровать?

OurKey.SetValue("Password", textBoxPassword.Text);
4b9b3361

Ответ 1

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

Хешируйте их, используя что-то вроде поставщика 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: Я думал, что мы просто говорим о аутентификации на линии фронта. Конечно, есть случаи, когда вы хотите зашифровать пароли для других вещей, которые должны быть обратимы, но должна быть блокировка с одним ходом поверх всего (за очень небольшим исключением).

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

Ответ 2

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

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

Чтобы сохранить хэши паролей:

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) Сохраните результат в базе данных своего магазина.

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

Изменить. По мере того, как исходная вычислительная мощность становится дешевле и быстрее, ценность хэширования или хребтов соления снижается. Джефф Атвуд имеет отличное обновление 2012 года, слишком длинное, чтобы повторить здесь полностью, в котором говорится:

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

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

Ответ 3

Это то, что вы хотели бы сделать:

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

Вы можете сделать это с помощью следующих классов. Этот класс является общим классом конечной точки клиента. Он позволяет IOC различных алгоритмов шифрования с помощью 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

Ответ 4

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

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

Если это просто для проверки подлинности, то достаточно использовать хэш.

Ответ 5

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

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

Ответ 7

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

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

Ответ 8

Том Скотт правильно понял, как (не) хранить пароли, на Computerphile.

https://www.youtube.com/watch?v=8ZtInClXe1Q

  • Если вы вообще этого не можете избежать, не пытайтесь самостоятельно хранить пароли. Используйте отдельную, заранее установленную, надежную платформу аутентификации пользователей (например, поставщики OAuth, ваша компания Active Домен каталога и т.д.).

  • Если вы должны хранить пароли, не следуйте инструкциям здесь. По крайней мере, не без консультации с более свежими и авторитетными публикациями, применимыми к вашему выбору. p >

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


Правильный способ хранения паролей изменяется со временем.

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


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

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

    • Не конвертировать во все-верхний регистр/все-строчные.
    • Не удалять пробелы.
    • Не снимайте неприемлемые символы или строки.
    • Не меняйте текстовое кодирование.
    • Не выполняйте никаких символов или строковых подстановок.
    • Не усекайте пароли любой длины.
  • Отклонить создание любых паролей, которые нельзя сохранить без изменений. Усиление вышеперечисленного. Если есть какая-то причина, ваш механизм хранения паролей не может надлежащим образом обрабатывать определенные символы, пробелы, строки или длины паролей, а затем возвращать ошибку и информировать пользователя об ограничениях системы, чтобы они могли повторить попытку с паролем, который в них помещается. Для лучшего удобства пользователей создайте список тех ограничений, которые доступны пользователю. Даже не беспокойтесь, не говоря уже о том, чтобы скрыть список от злоумышленников - они все равно поймут это самостоятельно.

  • Используйте длинную, случайную и уникальную соль для каждой учетной записи. Пароли без двух учетных записей никогда не будут выглядеть одинаково в хранилище, даже если пароли на самом деле идентичны.
  • Использовать медленные и криптографически сильные алгоритмы хеширования, предназначенные для использования с паролями. MD5, конечно, отсутствует. SHA-1/SHA-2 не идут. Но я не собираюсь говорить вам, что вы должны здесь использовать. (См. Первую пулю № 2 в этом сообщении.)
  • Итерации, насколько вы можете терпеть.. В то время как ваша система может иметь лучшие вещи, связанные с циклами процессора, чем хэш-пароли весь день, люди, которые будут взламывать ваши пароли, имеют системы, т. Сделайте так же сложно, как вы можете, не делая этого "слишком тяжело" на вас.

Самое главное...

Не слушайте кого-нибудь здесь.

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

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

Ответ 9

Я просмотрел весь пример для хорошего примера процесса шифрования и дешифрования, но большинство из них было чрезмерно сложным.

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

Итак, я написал процесс, который сделает это в упрощенном виде. Надеюсь, этот код полезен кому-то. Насколько я знаю, я могу в конечном итоге использовать это в другое время для другой компании/сайта.

public string GenerateAPassKey(string passphrase)
    {
        // Pass Phrase can be any string
        string passPhrase = passphrase;
        // Salt Value can be any string(for simplicity use the same value as used for the pass phrase)
        string saltValue = passphrase;
        // Hash Algorithm can be "SHA1 or MD5"
        string hashAlgorithm = "SHA1";
        // Password Iterations can be any number
        int passwordIterations = 2;
        // Key Size can be 128,192 or 256
        int keySize = 256;
        // Convert Salt passphrase string to a Byte Array
        byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
        // Using System.Security.Cryptography.PasswordDeriveBytes to create the Key
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
        //When creating a Key Byte array from the base64 string the Key must have 32 dimensions.
        byte[] Key = pdb.GetBytes(keySize / 11);
        String KeyString = Convert.ToBase64String(Key);

        return KeyString;
    }

 //Save the keystring some place like your database and use it to decrypt and encrypt
//any text string or text file etc. Make sure you dont lose it though.

 private static string Encrypt(string plainStr, string KeyString)        
    {            
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = 256;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.ECB;
        aesEncryption.Padding = PaddingMode.ISO10126;
        byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString);
        aesEncryption.Key = KeyInBytes;
        byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr);
        ICryptoTransform crypto = aesEncryption.CreateEncryptor();
        byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length);
        return Convert.ToBase64String(cipherText);
    }

 private static string Decrypt(string encryptedText, string KeyString) 
    {
        RijndaelManaged aesEncryption = new RijndaelManaged(); 
        aesEncryption.KeySize = 256;
        aesEncryption.BlockSize = 128; 
        aesEncryption.Mode = CipherMode.ECB;
        aesEncryption.Padding = PaddingMode.ISO10126;
        byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString);
        aesEncryption.Key = KeyInBytes;
        ICryptoTransform decrypto = aesEncryption.CreateDecryptor(); 
        byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length); 
        return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)); 
    }

 String KeyString = GenerateAPassKey("PassKey");
 String EncryptedPassword = Encrypt("25Characterlengthpassword!", KeyString);
 String DecryptedPassword = Decrypt(EncryptedPassword, KeyString);

Ответ 10

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

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

Ответ 11

.NET предоставляет услуги криптографии в классе, содержащемся в Пространство имен System.Security.Cryptography.

Ответ 12

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