AES256解密破坏了第一个字节

时间:2018-01-23 10:03:32

标签: c# aes

我已经解决了这个问题几个小时了,我仍然无法找到它发生的原因。

我有一个用AES加密的字符串,然后解密回原来的状态。但是,解密似乎修改了原始字符串,破坏了第一个字节。

而不是返回bc85f420763f79e6 9becb ...,而是返回?OqG?b3Mf~ J???j 9becb ...,然后继续返回其余的明文正确。

以下是我用来加密和解密的方法:

private byte[] EncryptAES256(string text, byte[] key)
{
    if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException("text");
    if (key == null || key.Length <= 0) throw new ArgumentNullException("key");

    byte[] encryptedText;
    try
    {
        AesManaged aes = new AesManaged();
        aes.Padding = PaddingMode.PKCS7;
        aes.GenerateIV();
        aes.Key = key;
        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {

                    swEncrypt.Write(text);
                }
                encryptedText = msEncrypt.ToArray();
            }
        }
    }
    catch (Exception ex)
    {
        Exception exceptionToBeThrown = new Exception(ex.Message, ex.InnerException);
        throw exceptionToBeThrown;
    }
    return encryptedText;
}

private string DecryptAES256(byte[] text, byte[] key)
{
    if (text == null || text.Length <= 0) throw new ArgumentNullException("text");
    if (key == null || key.Length <= 0) throw new ArgumentNullException("key");

    string decryptedText;
    try
    {
        AesManaged aes = new AesManaged();
        aes.Padding = PaddingMode.PKCS7;
        aes.GenerateIV();
        aes.Key = key;
        ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        using (MemoryStream msDecrypt = new MemoryStream(text))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {
                    decryptedText = srDecrypt.ReadToEnd();
                }
            }
        }
    }
    catch (Exception ex)
    {
        Exception exceptionToBeThrown = new Exception(ex.Message, ex.InnerException);
        throw exceptionToBeThrown;
    }
    return decryptedText;
}

我弄乱了什么吗?

2 个答案:

答案 0 :(得分:3)

加密和解密时使用的是不同的IV。 解密时,必须指定与加密数据时使用的IV相同的IV。

来自GenerateIV的文件(强调我的):

  

生成随机初始化向量(IV)以用于算法。

您可以使用在代码中定义的常量IV并传递给AesManaged实例,也可以存储用于加密数据的IV以及数据,然后在解密其余部分之前读取它。 / p>

答案 1 :(得分:3)

这是失败的原因是因为您没有设置IV键。相反,您为加密和解密方法生成两个不同的IV。

aes.GenerateIV();

每当您想要加密和解密数据时,您必须确保Salt en IV是相同的。您要做的是将加密方法中的IV添加到加密字节数组的开头。类似的东西:

byte[] IV = aesAlg.IV;
byte[] combinedIvCt = new byte[IV.Length + encrypted.Length];
Array.Copy(IV, 0, combinedIvCt, 0, IV.Length);
Array.Copy(encrypted, 0, combinedIvCt, IV.Length, encrypted.Length);

return Convert.ToBase64String(combinedIvCt.ToArray()); 

一旦解密,就会尝试解密加密结果的前16个字节。这将是你的IV键:

byte[] IV = new byte[16];
byte[] Encoded = new byte[inputAsByteArray.Length - IV.Length];
Array.Copy(inputAsByteArray, 0, IV, 0, IV.Length);
Array.Copy(inputAsByteArray, IV.Length, Encoded, 0, Encoded.Length);

//later in your code....
//Encoding = the data you are going to decrypt.  

aesAlg.IV = IV;

如果您想添加盐,也可以这样做。无论你做什么,但从不硬编码你的盐或IV。这是一本有趣的读物:https://security.stackexchange.com/questions/49031/is-it-safe-to-write-the-salt-and-or-the-iv-at-the-beggining-of-an-encrypted-file