Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate Rijndael KEY and IV using a passphrase?

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

like image 814
Predator Avatar asked Jun 26 '11 08:06

Predator


People also ask

How do you get AES key and IV?

GenerateKey() replaces the current key with a new random one (of size aes. KeySize). aes. GenerateIV() replaces the current IV with a new random one (of the block size, which is always 16 bytes for AES).

What is IV in rijndael?

The initialization vector (IV) to use for the symmetric algorithm.

How keys are generated in various cryptographic algorithms?

Computer cryptography uses integers for keys. In some cases keys are randomly generated using a random number generator (RNG) or pseudorandom number generator (PRNG). A PRNG is a computer algorithm that produces data that appears random under analysis.


3 Answers

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.

like image 152
Alex Aza Avatar answered Sep 18 '22 04:09

Alex Aza


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();
}
like image 42
Pan Pizza Avatar answered Sep 18 '22 04:09

Pan Pizza


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

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.

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.

like image 37
Bruno Rohée Avatar answered Sep 17 '22 04:09

Bruno Rohée