How to generate Rijndael KEY and IV using a passphrase? The key length must be in 256 bits.
I think you are looking for password-based key derivation. There is Rfc2898DeriveBytes
class that implements it.
Rfc2898DeriveBytes
takes a password, a salt, and an iteration count, and then generates keys through calls to the GetBytes
method.
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.
For more information about PBKDF2, see RFC 2898, "PKCS #5: Password-Based Cryptography Specification Version 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:
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.