Как создать Rijndael KEY и IV с использованием кодовой фразы? Длина ключа должна быть в 256 бит.
Как создать Rijndael KEY и IV с использованием кодовой фразы?
Ответ 1
Это код plug and play, который я нашел в Интернете. Он просто работает:
using System.IO;
using System.Security.Cryptography;
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
public static byte[] Encrypt(byte[] plain, string password)
{
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
rijndael.Key = pdb.GetBytes(32);
rijndael.IV = pdb.GetBytes(16);
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(plain, 0, plain.Length);
cryptoStream.Close();
return memoryStream.ToArray();
}
public static byte[] Decrypt(byte[] cipher, string password)
{
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
rijndael.Key = pdb.GetBytes(32);
rijndael.IV = pdb.GetBytes(16);
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(cipher, 0, cipher.Length);
cryptoStream.Close();
return memoryStream.ToArray();
}
Ответ 2
Я думаю, что вы ищете деривацию ключей на основе пароля. Существует класс Rfc2898DeriveBytes
, который его реализует.
Rfc2898DeriveBytes
берет пароль, соль и счетчик итераций, а затем генерирует ключи через вызовы методу GetBytes
.
RFC 2898 включает в себя способы создания ключа и вектора инициализации (IV) из пароля и соли. Вы можете использовать PBKDF2, основанную на пароле функцию деривации ключа, для получения ключей с использованием псевдослучайной функции, которая позволяет генерировать ключи практически неограниченной длины. Класс Rfc2898DeriveBytes может использоваться для создания производного ключа из базового ключа и других параметров. В функции деривации ключа на основе пароля базовый ключ - это пароль, а остальные параметры - значение соли и счетчик итераций.
Для получения дополнительной информации о PBKDF2 см. RFC 2898, "PKCS №5: Спецификация криптографии на основе паролей версии 2.0".
Пример:
public static byte[] CreateKey(string password)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 9872;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
return rfc2898DeriveBytes.GetBytes(32);
}
Вы можете использовать DeriveBytes
в любом симметричном алгоритме, а не только Rijndael
.
Пример:
public static SymmetricAlgorithm InitSymmetric(SymmetricAlgorithm algorithm, string password, int keyBitLength)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 234;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
{
if (!algorithm.ValidKeySize(keyBitLength))
throw new InvalidOperationException("Invalid size key");
algorithm.Key = rfc2898DeriveBytes.GetBytes(keyBitLength / 8);
algorithm.IV = rfc2898DeriveBytes.GetBytes(algorithm.BlockSize / 8);
return algorithm;
}
}
private static byte[] Transform(byte[] bytes, Func<ICryptoTransform> selectCryptoTransform)
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, selectCryptoTransform(), CryptoStreamMode.Write))
cryptoStream.Write(bytes, 0, bytes.Length);
return memoryStream.ToArray();
}
}
Использование:
public static void Main()
{
using (var rijndael = InitSymmetric(Rijndael.Create(), "TestPassword", 256))
{
var text = "Some text to encrypt";
var bytes = Encoding.UTF8.GetBytes(text);
var encryptedBytes = Transform(bytes, rijndael.CreateEncryptor);
var decryptedBytes = Transform(encryptedBytes, rijndael.CreateDecryptor);
var decryptedText = Encoding.UTF8.GetString(decryptedBytes);
Debug.Assert(text == decryptedText);
}
}
Убедитесь, что вы изменили параметры salt
и iterations
.
Ответ 3
IV должен быть случайным (необязательно быть непредсказуемым случайным, достаточно случайным, чтобы они не были повторно использованы).
Что касается генерации ключа из пароля, вы ищете функцию деривации ключей, для которой в настоящее время существует как минимум три хороших варианта ( PBKDF2, bcrypt, scrypt), используя нетерированный хэш в качестве предыдущего плаката, чаще всего приводит к небезопасным системам.
Также используйте AES или Rijndael, это не совсем то же самое. Использование комбинации Rijndael, не входящей в AES, может быть коучиком в отношении взаимодействия позже, и безопасность этих комбинаций функций пока не изучена.
Ответ 4
IV должен быть случайным (вы обычно передаете его вместе с зашифрованными данными), а ключ может быть получен несколькими способами: просто вставьте пароль в длину ключа (если пароль короче 32 символов ) или (что более надежно) вывести ключ с помощью алгоритма хеширования SHA2 или использовать более сложный способ.
Ответ 5
Используйте класс Rfc2898DeriveBytes.
В то же время ваш уровень безопасности упал/был ограничен длиной/силой парольной фразы. Итак, не делайте этого.