[ACCEPTED]-How to generate Rijndael KEY and IV using a passphrase?-rijndael

Accepted answer
Score: 61

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

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

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

For 5 more information about PBKDF2, see RFC 2898, "PKCS 4 #5: Password-Based Cryptography Specification 3 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 2 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 1 sure you change salt and iterations parameters.

Score: 45

This is plug and play code that I found 1 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();
}
Score: 9

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

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

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

Score: 4

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

Score: 2

Use this Rfc2898DeriveBytes Class.

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

Score: 0

Other answers contain way more information. The 3 answer to this question where you only want 2 to generate the key and IV given a passphrase 1 use:

        // use something more random in real life
        var salt =  new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

        string password = "my-password";
        Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, salt);
        var key = pdb.GetBytes(32);
        var iv = pdb.GetBytes(16);

More Related questions