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

Как создать Rijndael KEY и IV с использованием кодовой фразы?

Как создать Rijndael KEY и IV с использованием кодовой фразы? Длина ключа должна быть в 256 бит.

4b9b3361

Ответ 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.

В то же время ваш уровень безопасности упал/был ограничен длиной/силой парольной фразы. Итак, не делайте этого.