Почему мне нужно использовать класс Rfc2898DeriveBytes (в.NET) вместо прямого использования пароля в качестве ключа или IV?
В чем разница между использованием Rfc2898DeriveBytes и просто использованием Encoding.ASCII.GetBytes(string object);
?
У меня был относительный успех с любым из этих подходов, первый - более длительный подход, в то время как последний прост и понятен. Похоже, что оба в конечном итоге позволяют вам сделать то же самое, но я изо всех сил пытаюсь увидеть смысл в использовании первого над вторым.
Основная концепция, которую я смог понять, заключается в том, что вы можете преобразовать строковые пароли в байтовые массивы, которые будут использоваться, например, для симметричного класса шифрования, AesManaged
, Через класс RFC, но вы можете использовать солт-значения и пароль при создании объекта rfc. Я предполагаю, что это более безопасно, но в лучшем случае это необразованное предположение! Кроме того, это позволяет вам возвращать байтовые массивы определенного размера, ну что-то в этом роде.
Вот несколько примеров, чтобы показать вам, откуда я:
byte[] myPassinBytes = Encoding.ASCII.GetBytes("some password");
или же
string password = "P@%5w0r]>";
byte[] saltArray = Encoding.ASCII.GetBytes("this is my salt");
Rfc2898DeriveBytes rfcKey = new Rfc2898DeriveBytes(password, saltArray);
Объект 'rfcKey' теперь можно использовать для настройки свойств.Key или.IV в классе алгоритма симметричного шифрования.
то есть.
RijndaelManaged rj = new RijndaelManaged ();
rj.Key = rfcKey.Getbytes(rj.KeySize / 8);
rj.IV = rfcKey.Getbytes(rj.Blocksize / 8);
'RJ' должен быть готов к работе!
Запутывающая часть... поэтому, вместо использования объекта 'rfcKey', я могу не просто использовать мой массив 'myPassInBytes', чтобы помочь настроить мой объект 'rj'?
Я попытался сделать это в VS2008, и немедленный ответ - НЕТ. Но получили ли вы, ребята, более образованный ответ о том, почему класс RFC используется по сравнению с другой альтернативой, которую я упомянул выше?
1 ответ
Вы действительно, действительно, не хотите использовать пароль пользователя непосредственно в качестве ключа шифрования, особенно с AES.
Rfc2898DeriveBytes является реализацией PBKDF2. Он постоянно хеширует пароль пользователя вместе с солью. Это имеет несколько преимуществ:
Во-первых, вы можете использовать пароли произвольного размера - AES поддерживает только определенные размеры ключей.
Во-вторых, добавление соли означает, что вы можете использовать одну и ту же фразу-пароль для генерации нескольких разных ключей (при условии, что соль не является константой, как в вашем примере). Это важно для разделения ключей; Повторное использование ключей в разных контекстах является одним из наиболее распространенных способов взлома криптографических систем.
Многократные итерации (по умолчанию 1000) замедляют атаки по подбору пароля. Рассмотрим кого-то, кто пытается угадать ваш ключ AES. Если вы просто использовали пароль, это было бы просто - просто попробуйте каждый возможный пароль в качестве ключа. С другой стороны, в PBKDF2 злоумышленник сначала должен выполнить 1000 итераций хеша для каждого предположения пароля. Таким образом, хотя он лишь немного замедляет пользователя, он оказывает непропорциональное влияние на злоумышленника. (На самом деле, довольно часто используются гораздо более высокие числа итераций; обычно рекомендуется 10000).
Это также означает, что окончательный выходной ключ распределен равномерно. Например, если вы используете пароль, то 16 из 128 бит ключа будут равны 0 (старший бит ASCII). Это сразу же делает поиск ключей в 65536 раз проще, чем следовало бы, даже игнорируя угадывание пароля.
Наконец, у AES есть определенные уязвимости с соответствующими ключевыми атаками. Атаки по связанному ключу возможны, когда злоумышленнику известны некоторые данные, зашифрованные несколькими ключами, и между ними существует известная (или предполагаемая) связь. Например, если вы зашифровали данные как с помощью пароля-пароля "Мой ключ AES отстой" (16 байт, для AES-128), так и с "MY AES KEY SUCKS", возможна атака по связанному ключу. Наиболее известные в настоящее время атаки фактически не позволяют таким образом полностью взломать AES, но со временем они постепенно улучшаются - только на прошлой неделе была опубликована новая атака, которая разбивает 13 раундов (из 14 общих) AES-256 с использованием связанная ключевая атака. Было бы крайне неразумно полагаться на то, что такие атаки не улучшатся со временем.
Краткий ответ: это безопаснее. По той же причине в пространстве имен System.Security есть специальный генератор случайных чисел.
Для получения дополнительной информации см. RFC2898.
Я понимаю одну маленькую часть:
с Encoding.ASCII.GetBytes(), когда вы используете длинный пароль, вы будете использовать не более первых его байтов rj.KeySize. Остальное игнорируется. А когда ваш пароль короче, чем размер ключа, вам придется добавить отступы (и просто добавление последовательности нулей увеличивает уязвимость).