从加密文本中获取IV以用于解密方法

时间:2018-10-08 16:26:36

标签: c# asp.net encryption cryptography aes

我正在尝试使用AES256算法进行加密和解密,我有以下代码。

 public string Encrypt(string dataToEncrypt, string key)
            {
                if (dataToEncrypt == null || dataToEncrypt.Length <= 0)
                    throw new ArgumentNullException("plainText");
                if (key == null || key.Length <= 0)
                    throw new ArgumentNullException("Key");
                var iv = GenerateRandomNumber(16);
                using (var aes = new AesCryptoServiceProvider())
                {
                    aes.Mode = CipherMode.CBC;
                    aes.Padding = PaddingMode.PKCS7;
                    aes.Key = Convert.FromBase64String(key);
                    aes.IV = iv;
                    byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
                    using (var memoryStream = new MemoryStream())
                    {
                        var cryptoStream = new CryptoStream(memoryStream, 
                       aes.CreateEncryptor(),
                            CryptoStreamMode.Write);
                        cryptoStream.Write(data, 0, data.Length);
                        cryptoStream.FlushFinalBlock();                    
                        return Convert.ToBase64String(memoryStream.ToArray());
                    }
                }
            }
  public string DecryptReturnsString(string dataToDecrypt, string key)
        {
            if (dataToDecrypt == null || dataToDecrypt.Length <= 0)
                throw new ArgumentNullException("dataToDecrypt");

            if (key == null || key.Length <= 0)
                throw new ArgumentNullException("Key");

            using (var aes = new AesCryptoServiceProvider())
            {
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                aes.Key = Convert.FromBase64String(key);
                byte[] data= Convert.FromBase64String(dataToDecrypt);
                aes.IV = getIV(data);
                using (var memoryStream = new MemoryStream())
                {
                    var cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(),
                        CryptoStreamMode.Write);

                    cryptoStream.Write(data, 0, data.Length);
                    cryptoStream.FlushFinalBlock();

                    var decryptBytes = Encoding.UTF8.GetString(memoryStream.ToArray());

                    return decryptBytes;
                }
            }
        }

   public byte[] GenerateRandomNumber(int length)
        {
            using (var randomNumberGenerator = new RNGCryptoServiceProvider())
            {
                var randomNumber = new byte[length];
                randomNumberGenerator.GetBytes(randomNumber);

                return randomNumber;
            }
        }
        private static byte[] getIV(byte[] arr)
        {
            byte[] IV = new byte[16];
            Array.Copy(arr, 0, IV, 0, 16);
            return IV;
        }

在这里,我尝试从加密的字符串中获取IV,但是在调试时,最初生成的IV和提取的IV是不同的,因此它给了我一个例外,即“填充无效且无法删除。” / p>

任何人都可以看看我的GetIV()方法,让我知道我在哪里做错了。

2 个答案:

答案 0 :(得分:0)

在CBC操作模式下的IV必须以纯文本形式发送,否则无法解密。这没有安全问题。

如罗伯特所说,将其放在流的开头。

see

var mergedStream = new MergedStream(new Stream 
{
    new MemoryStream(iv),
    cryptoStream,
}

答案 1 :(得分:0)

有两个问题。

  1. 似乎您不是沿着密文发送IV(本身并没有完成)。惯常做法是将IV放在密文之前。因此,正如罗伯特(Robert)所说,您可以在加密之前直接将IV写入内存流

  2. 解密时,您可以读取IV(数据的第一个字节,但仅解密其余部分(子数组16 .. length)