如何使用密码短语生成Rijndael KEY和IV?

时间:2021-12-23 18:24:56

How to generate Rijndael KEY and IV using a passphrase? The key length must be in 256 bits.

如何使用密码短语生成Rijndael KEY和IV?密钥长度必须为256位。

5 个解决方案

#1


35  

This is plug and play code that I found on internet. It just works:

这是我在互联网上找到的即插即用代码。它只是工作:

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


55  

I think you are looking for password-based key derivation. There is Rfc2898DeriveBytes class that implements it.

我认为您正在寻找基于密码的密钥派生。有Rfc2898DeriveBytes类来实现它。

Rfc2898DeriveBytes takes a password, a salt, and an iteration count, and then generates keys through calls to the GetBytes method.

Rfc2898DeriveBytes获取密码,salt和迭代计数,然后通过调用GetBytes方法生成密钥。

RFC 2898 includes methods for creating a key and initialization vector (IV) from a password and salt. You can use PBKDF2, a password-based key derivation function, to derive keys using a pseudo-random function that allows keys of virtually unlimited length to be generated. The Rfc2898DeriveBytes class can be used to produce a derived key from a base key and other parameters. In a password-based key derivation function, the base key is a password and the other parameters are a salt value and an iteration count.

RFC 2898包括用于从密码和盐创建密钥和初始化向量(IV)的方法。您可以使用基于密码的密钥派生函数PBKDF2,使用伪随机函数导出密钥,该函数允许生成几乎无限长度的密钥。 Rfc2898DeriveBytes类可用于从基本密钥和其他参数生成派生密钥。在基于密码的密钥派生函数中,基本密钥是密码,其他参数是salt值和迭代计数。

For more information about PBKDF2, see RFC 2898, "PKCS #5: Password-Based Cryptography Specification Version 2.0,".

有关PBKDF2的更多信息,请参阅RFC 2898,“PKCS#5:基于密码的加密规范版本2.0”。

Example:

例:

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);
}

You can use DeriveBytes in any symmetric algorithm, not just Rijndael.
Example:

您可以在任何对称算法中使用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();
    }
}

Usage:

用法:

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);
    }
}

Make sure you change salt and iterations parameters.

确保更改salt和iterations参数。

#3


9  

The IV must be random (doesn't need to be an unpredictable random, just random enough that they won't be reused).

IV必须是随机的(不需要是一个不可预测的随机,只是随机的,它们不会被重用)。

As to generating the key from the password, you are looking for a key derivation function for which nowadays there are at least three good choices (PBKDF2, bcrypt, scrypt), using a non iterated hash as a previous poster suggests more often than not leads to insecure systems.

至于从密码生成密钥,你正在寻找一个密钥派生函数,现在至少有三个不错的选择(PBKDF2,bcrypt,scrypt),使用非迭代哈希,因为之前的海报建议更多的是不安全的系统。

Also use AES nor Rijndael, that's not exactly the same thing. Using a Rijndael combination not part of AES could be an inter-operability nightmare later, and the security of those functions combination isn't well studied anyway.

也使用AES或Rijndael,这不完全相同。使用Rijndael组合不是AES的一部分可能是后来的互操作性噩梦,并且无论如何这些功能组合的安全性都没有得到很好的研究。

#4


4  

IV must be random (you usually pass it together with the encrypted data), and the key can be derived in a number of ways: simply pad the password to the length of the key (if the password is shorter than 32 characters) or (which is more reliable) derive a key by using SHA2 hashing algorithm or use some more sophisticated way.

IV必须是随机的(您通常将其与加密数据一起传递),并且密钥可以通过多种方式派生:只需将密码填充到密钥的长度(如果密码短于32个字符)或(哪个更可靠)通过使用SHA2散列算法或使用更复杂的方法来导出密钥。

#5


2  

Use this Rfc2898DeriveBytes Class.

使用此Rfc2898DeriveBytes类。

Word of advise though, your security level has dropped/limited by the passphrase length/strength. So, don't do it.

建议的话,你的安全级别已经下降/受密码长度/强度的限制。所以,不要这样做。

#1


35  

This is plug and play code that I found on internet. It just works:

这是我在互联网上找到的即插即用代码。它只是工作:

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


55  

I think you are looking for password-based key derivation. There is Rfc2898DeriveBytes class that implements it.

我认为您正在寻找基于密码的密钥派生。有Rfc2898DeriveBytes类来实现它。

Rfc2898DeriveBytes takes a password, a salt, and an iteration count, and then generates keys through calls to the GetBytes method.

Rfc2898DeriveBytes获取密码,salt和迭代计数,然后通过调用GetBytes方法生成密钥。

RFC 2898 includes methods for creating a key and initialization vector (IV) from a password and salt. You can use PBKDF2, a password-based key derivation function, to derive keys using a pseudo-random function that allows keys of virtually unlimited length to be generated. The Rfc2898DeriveBytes class can be used to produce a derived key from a base key and other parameters. In a password-based key derivation function, the base key is a password and the other parameters are a salt value and an iteration count.

RFC 2898包括用于从密码和盐创建密钥和初始化向量(IV)的方法。您可以使用基于密码的密钥派生函数PBKDF2,使用伪随机函数导出密钥,该函数允许生成几乎无限长度的密钥。 Rfc2898DeriveBytes类可用于从基本密钥和其他参数生成派生密钥。在基于密码的密钥派生函数中,基本密钥是密码,其他参数是salt值和迭代计数。

For more information about PBKDF2, see RFC 2898, "PKCS #5: Password-Based Cryptography Specification Version 2.0,".

有关PBKDF2的更多信息,请参阅RFC 2898,“PKCS#5:基于密码的加密规范版本2.0”。

Example:

例:

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);
}

You can use DeriveBytes in any symmetric algorithm, not just Rijndael.
Example:

您可以在任何对称算法中使用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();
    }
}

Usage:

用法:

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);
    }
}

Make sure you change salt and iterations parameters.

确保更改salt和iterations参数。

#3


9  

The IV must be random (doesn't need to be an unpredictable random, just random enough that they won't be reused).

IV必须是随机的(不需要是一个不可预测的随机,只是随机的,它们不会被重用)。

As to generating the key from the password, you are looking for a key derivation function for which nowadays there are at least three good choices (PBKDF2, bcrypt, scrypt), using a non iterated hash as a previous poster suggests more often than not leads to insecure systems.

至于从密码生成密钥,你正在寻找一个密钥派生函数,现在至少有三个不错的选择(PBKDF2,bcrypt,scrypt),使用非迭代哈希,因为之前的海报建议更多的是不安全的系统。

Also use AES nor Rijndael, that's not exactly the same thing. Using a Rijndael combination not part of AES could be an inter-operability nightmare later, and the security of those functions combination isn't well studied anyway.

也使用AES或Rijndael,这不完全相同。使用Rijndael组合不是AES的一部分可能是后来的互操作性噩梦,并且无论如何这些功能组合的安全性都没有得到很好的研究。

#4


4  

IV must be random (you usually pass it together with the encrypted data), and the key can be derived in a number of ways: simply pad the password to the length of the key (if the password is shorter than 32 characters) or (which is more reliable) derive a key by using SHA2 hashing algorithm or use some more sophisticated way.

IV必须是随机的(您通常将其与加密数据一起传递),并且密钥可以通过多种方式派生:只需将密码填充到密钥的长度(如果密码短于32个字符)或(哪个更可靠)通过使用SHA2散列算法或使用更复杂的方法来导出密钥。

#5


2  

Use this Rfc2898DeriveBytes Class.

使用此Rfc2898DeriveBytes类。

Word of advise though, your security level has dropped/limited by the passphrase length/strength. So, don't do it.

建议的话,你的安全级别已经下降/受密码长度/强度的限制。所以,不要这样做。