Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symmetric Encryption (AES): Is saving the IV and Salt alongside the encrypted data safe and proper?

I am trying to make sense of how to handle and manage an initilization vector and salt (when applicable) when encrypting and decrypting data using a symmetric encryption algorithm, in this case AES.

I have deduced from different SO threads and various other websites that neither the IV or salt need to be secret, only unique in order to defend against cryptanalytic attacks such as a brute-force attack. With this in mind I figured that it would be viable to store my pseudo random IV with the encrypted data. I am asking if the method I am using is proper and furthermore, should I be treating my currently hard coded salt in the same manner? That being writing it to the memory stream along side the IV

My code:

private const ushort ITERATIONS = 300;
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22,  0x3c };

private static byte[] CreateKey(string password, int keySize)
{
    DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, SALT, ITERATIONS);
    return derivedKey.GetBytes(keySize >> 3);
}

public static byte[] Encrypt(byte[] data, string password)
{
    byte[] encryptedData = null;
    using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
    {
        provider.GenerateIV();
        provider.Key = CreateKey(password, provider.KeySize);
        provider.Mode = CipherMode.CBC;
        provider.Padding = PaddingMode.PKCS7;

        using (MemoryStream memStream = new MemoryStream(data.Length))
        {
            memStream.Write(provider.IV, 0, 16);
            using (ICryptoTransform encryptor = provider.CreateEncryptor(provider.Key, provider.IV))
            {
                using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(data, 0, data.Length);
                    cryptoStream.FlushFinalBlock();
                }
            }
            encryptedData = memStream.ToArray();
        }
    }
    return encryptedData;
}

public static byte[] Decrypt(byte[] data, string password)
{
    byte[] decryptedData = new byte[data.Length];
    using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
    {
        provider.Key = CreateKey(password, provider.KeySize);
        provider.Mode = CipherMode.CBC;
        provider.Padding = PaddingMode.PKCS7;
        using (MemoryStream memStream = new MemoryStream(data))
        {
            byte[] iv = new byte[16];
            memStream.Read(iv, 0, 16);
            using (ICryptoTransform decryptor = provider.CreateDecryptor(provider.Key, iv))
            {
                using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read))
                {
                    cryptoStream.Read(decryptedData, 0, decryptedData.Length);
                }
            }
        }
    }
    return decryptedData;
}

I am also open to any other information about symmetric encryption with regards to proper practice.

like image 439
Caster Troy Avatar asked Dec 16 '12 13:12

Caster Troy


People also ask

What is AES symmetric encryption?

The Advanced Encryption Standard (AES) is a symmetric block cipher chosen by the U.S. government to protect classified information. AES is implemented in software and hardware throughout the world to encrypt sensitive data. It is essential for government computer security, cybersecurity and electronic data protection.

Does AES encryption use salt?

AES doesn't have a concept of a salt. It just takes data, and a key. For the same input, it will always generate the same output. How you combine your message with your salt is up to you.

What is salt and IV in AES?

Salt is necessary to prevent pre-computation attacks. An IV (or nonce with counter modes) makes the same plain text produce different cipher texts. The prevents an attacker from exploiting patterns in the plain text to garner information from a set of encrypted messages.

What is the use of IV in AES encryption?

An initialization vector (or IV) are used to ensure that the same value encrypted multiple times, even with the same secret key, will not always result in the same encrypted value. This is an added security layer.


2 Answers

Storing the IV and Salt along with the cipher text is proper and a best practice. Hard coding the salt is not useful, being random is important, hard coding the iterations is perfectly okay but is typically much higher than 300 (in fact at least 1000 and you typically go much higher if your machine/usage can handle it as in 10s of thousands).

Because I've seen so many bad (or old) examples of c# encryption from stack overflow cut and paste into open source code, I wrote a short bit of cut and paste encryption code Modern Examples of Symmetric Authenticated Encryption of a string. that i try to keep up to date and reviewed. It stores the iv and salt with the ciphertext it also authenticates the ciphertext and values included with the cipher text.

Ideally though a better practice would be to use a high level encryption library that would handle best practices like the iv for you, however those typically haven't existed for csharp. I've been working on a native csharp version of google's keyczar library. While it's functionally ready for use, I've been wanting to get more eyes on the code before the first official stable release.

like image 119
jbtule Avatar answered Nov 15 '22 16:11

jbtule


Yes, both the IV and salt are public values. What's more important is ensuring these are random values for each encryption operation.

To give an example of this in the wild, take a look at the rncryptor data format. Here the salt and IV are packaged into a data format, along with the ciphertext and a MAC value. (Note: this is an objective-c example).

like image 34
Duncan Jones Avatar answered Nov 15 '22 16:11

Duncan Jones