2014-11-24 5 views
1

Поэтому я хэширование паролей к базе данных с помощью класса Rcfc2898DeriveBytes в .NETЗапоминание PBKDF2 итерации

Все работает отлично для перемешивания и хранения как окончательного хэша и соли.

Однако у меня возникла проблема при определении количества итераций, выполняемых классом при хешировании пароля.

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

Я вижу, что bcrypt сделает все это за вас, но у меня нет роскоши для добавления библиотеки в проект.

Каков наилучший способ сохранить это число и как я буду делать это, чтобы он был извлечен, а не просто потерян в хеше при хранении (как бы отделить его от хэша, как только я его верну)?

Благодарим за любые советы и информацию раньше времени!

ответ

1

Я нашел то, что искал по указанному ниже URL.

https://cmatskas.com/-net-password-hashing-using-pbkdf2/

Соответствующий код здесь:

public class PasswordHash 
{ 
    public const int SALT_BYTE_SIZE = 24; 
    public const int HASH_BYTE_SIZE = 20; 
    public const int PBKDF2_ITERATIONS = 1000; 
    public const int ITERATION_INDEX = 0; 
    public const int SALT_INDEX = 1; 
    public const int PBKDF2_INDEX = 2; 

    public static string HashPassword(string password) 
    { 
     var cryptoProvider = new RNGCryptoServiceProvider(); 
     byte[] salt = new byte[SALT_BYTE_SIZE]; 
     cryptoProvider.GetBytes(salt); 

     var hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE); 
     return PBKDF2_ITERATIONS + ":" + 
       Convert.ToBase64String(salt) + ":" + 
       Convert.ToBase64String(hash); 
    } 

    public static bool ValidatePassword(string password, string correctHash) 
    { 
     char[] delimiter = { ':' }; 
     var split = correctHash.Split(delimiter); 
     var iterations = Int32.Parse(split[ITERATION_INDEX]); 
     var salt = Convert.FromBase64String(split[SALT_INDEX]); 
     var hash = Convert.FromBase64String(split[PBKDF2_INDEX]); 

     var testHash = PBKDF2(password, salt, iterations, hash.Length); 
     return SlowEquals(hash, testHash); 
    } 
} 

Я взял метод HashPassword, чтобы сохранить свои ценности в базу данных для последующего использования. Я использовал ValidatePassword, чтобы вернуть их обратно для использования. Он работал как шарм и позволял мне делать размер байтов для соли и хеша, а также количество переменных итераций на основе необходимой силы. Значения хранятся только в конфигурационном файле Web/App.

Благодарим за ответы всем!

0

Посмотрите на то, как Bcrypt хранит хэши здесь: What column type/length should I use for storing a Bcrypt hashed password in a Database?

Так что, если вы только планируете изменить итераций, вы могли бы пойти на что-то простое, как это:

$<number of iterations>$<hash> 
+1

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

0

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

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

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

+0

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