Question

I have been doing some research into using AESCryptoServiceProvider in C#. So far, I have an implementation which seems to be working. However, my understanding of initialization vectors is that it should protect my cipher text from being the same when the payload and key are the same, but it appears I am doing something wrong. Changing my initialization vector doesn't seem to affect the results of these functions at all.

Here are my functions:

public string EncryptString(string toEncrypt, byte[] encryptionKey, byte[] iv)
{
    var toEncryptBytes = Encoding.Default.GetBytes(toEncrypt);
    using (var aes = new AesCryptoServiceProvider())
    {
        aes.Key = encryptionKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        //aes.GenerateIV();
        aes.IV = iv;

        using (var encryptor = aes.CreateEncryptor(encryptionKey, aes.IV))
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            using (var bWriter = new BinaryWriter(cs))
            {
                bWriter.Write(aes.IV, 0, aes.IV.Length);
                bWriter.Write(toEncryptBytes, 0, toEncryptBytes.Length);
                cs.FlushFinalBlock();
            }
            return Convert.ToBase64String(ms.ToArray());
        }
    }
}

public string DecryptString(string toDecrypt, byte[] encryptionKey, byte[] iv)
{
    using (var aes = new AesCryptoServiceProvider())
    {
        aes.Key = encryptionKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        var toDecryptBytes = Convert.FromBase64String(toDecrypt);

        Array.Copy(toDecryptBytes, 0, iv, 0, iv.Length);
        aes.IV = iv;

        using (var ms = new MemoryStream())
        {
             using (var cs = new CryptoStream(ms, aes.CreateDecryptor(aes.Key, iv), CryptoStreamMode.Write))
             using (var binWriter = new BinaryWriter(cs))
             {
                 binWriter.Write(toDecryptBytes, iv.Length, toDecryptBytes.Length - iv.Length);
             }
             return Encoding.Default.GetString(ms.ToArray());
        }
    }
}

New version of my encrypt function I have now following the advice from @owlstead, changing back CBC mode. This does appear to be working correctly now using CBC.

public string EncryptString(string toEncrypt, byte[] encryptionKey)
{
    var toEncryptBytes = Encoding.Default.GetBytes(toEncrypt);
    using (var aes = new AesCryptoServiceProvider())
    {
        aes.Key = encryptionKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.GenerateIV();

        using (var encryptor = aes.CreateEncryptor(encryptionKey, aes.IV))
        using (var ms = new MemoryStream())
        {
             ms.Write(aes.IV, 0, aes.IV.Length);
             using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
             using (var bWriter = new BinaryWriter(cs))
             {
                 bWriter.Write(toEncryptBytes, 0, toEncryptBytes.Length);
                 cs.FlushFinalBlock();
             }
             return Convert.ToBase64String(ms.ToArray());
        }
    }
}
Was it helpful?

Solution

You are putting the CryptoStream and the BinaryWriter in the wrong order for at least the encrypt function. You are currently encrypting your IV, while the IV should be put in front of the ciphertext, in plain.

The IV is XORed with the plain text before encryption. Now, this means that you zero out the plain text: you are encrypting a zero valued block.

OTHER TIPS

CipherMode.ECB mode seems not picking up the IV argument(which means no matter what IV you passed in, the result will be the same),this is possible because ECB doesn't need a concept as Initial Vector,for there's no subsequent vectors either. If you want to mask your ECB block, XOR your block mannually before encryption is OK. While you changed to CipherMode.CBC, the IV does matters,for subsequent blocks will be XORed with previous encrypted block ,as forms a chain.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top