【问题标题】:C# AES encryption / decryption returning incorrect resultC# AES 加密/解密返回不正确的结果
【发布时间】:2015-08-29 22:29:04
【问题描述】:

我在这里基于 MSDN 示例创建了一个简单的 AES 加密/解密服务:https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes(v=vs.110).aspx

这是我的代码,带有一个调用函数和一个用于测试的硬编码键:

public class AesEncryptionService
{
    private const int InitializationVectorLength = 16;
    private static readonly byte[] Key = Convert.FromBase64String("W+jcxfBJm37AAZujiktg4qCdy3k8D+vIrj4exFxFpIY=");

    public byte[] Encrypt(byte[] input)
    {
        using (var aes = Aes.Create())
        {
            aes.Key = Key;

            Console.WriteLine("Key: " + Convert.ToBase64String(aes.Key));
            Console.WriteLine("IV: " + Convert.ToBase64String(aes.IV));
            Console.WriteLine("Input: " + Convert.ToBase64String(input));

            using (var outputStream = new MemoryStream())
            {
                using (var encryptor = aes.CreateEncryptor())
                using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
                using (var streamWriter = new StreamWriter(cryptoStream))
                {
                    streamWriter.Write(input);
                }

                var output = outputStream.ToArray();
                Console.WriteLine("Output: " + Convert.ToBase64String(output));

                var encrypted = aes.IV.Concat(output).ToArray();
                return encrypted;
            }
        }
    }

    public byte[] Decrypt(byte[] input)
    {
        var initializationVector = input.Take(InitializationVectorLength).ToArray();
        input = input.Skip(InitializationVectorLength).ToArray();

        using (var aes = Aes.Create())
        {
            aes.Key = Key;
            aes.IV = initializationVector;

            Console.WriteLine("Key: " + Convert.ToBase64String(aes.Key));
            Console.WriteLine("IV: " + Convert.ToBase64String(aes.IV));
            Console.WriteLine("Input: " + Convert.ToBase64String(input));

            using (var outputStream = new MemoryStream())
            {
                using (var decryptor = aes.CreateDecryptor())
                using (var inputStream = new MemoryStream(input))
                using (var cryptoStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read))
                {
                    cryptoStream.CopyTo(outputStream);
                }

                var output = outputStream.ToArray();
                Console.WriteLine("Output: " + Convert.ToBase64String(output));

                return output;
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var encryptionService = new AesEncryptionService();
        var input = Guid.NewGuid().ToByteArray();

        Console.WriteLine("Encrypting...");
        var encrypted = encryptionService.Encrypt(input);
        Console.WriteLine();
        Console.WriteLine("Decrypting...");
        var decrypted = encryptionService.Decrypt(encrypted);
        Console.WriteLine();
        Console.WriteLine("Input: " + Convert.ToBase64String(input));
        Console.WriteLine("Output: " + Convert.ToBase64String(decrypted));
    }
}

这是我得到的输出示例:

Encrypting...
Key: W+jcxfBJm37AAZujiktg4qCdy3k8D+vIrj4exFxFpIY=
IV: 7tb1BwOOcCdH/h1wdUmrtw==
Input: UsyLMdqbuUC5cVW/+p6vWA==
Output: 4KAhNOwNiNpmPxjvvx38cA==

Decrypting...
Key: W+jcxfBJm37AAZujiktg4qCdy3k8D+vIrj4exFxFpIY=
IV: 7tb1BwOOcCdH/h1wdUmrtw==
Input: 4KAhNOwNiNpmPxjvvx38cA==
Output: U3lzdGVtLkJ5dGVbXQ==

Input: UsyLMdqbuUC5cVW/+p6vWA==
Output: U3lzdGVtLkJ5dGVbXQ==

如您所见,解密后的输出与输入不匹配。我一定在某处的代码中犯了错误,但我似乎无法发现它......有人可以帮忙吗?

【问题讨论】:

  • 我不确定,但在我看来,您将 IV 置于加密阶段的末尾,然后将 IV 置于解密阶段的开头。我从未使用过 .Take 方法,所以我不确定。会是这样吗?
  • 不,我将 IV 放在加密阶段的最前面。您可以在示例输出中看到 IV 匹配。

标签: c# .net encryption cryptography aes


【解决方案1】:

Microsoft 的示例使用StreamWriter,它与string 一起使用。您使用byte[],但仍使用StreamWriter,其重载成员Write(object) 在内部调用对象上的ToString()。当您在byte[] 上调用ToString() 时,您总是会得到“System.Byte[]”作为字符串。 13 个字节,就像最终结果一样。实际上,如果在最后一行替换

Console.WriteLine("Output: " + Convert.ToBase64String(decrypted));

Console.WriteLine("Output: " + Encoding.UTF8.GetString(decrypted));

这正是你看到的字符串。

您应该使用BinaryWriter 而不是StreamWriter

【讨论】:

  • 完美,谢谢。我不敢相信我没有发现无论随机输入是什么,我总是得到完全相同的输出!
猜你喜欢
  • 1970-01-01
  • 2012-03-12
  • 2020-12-13
  • 1970-01-01
  • 2014-05-14
  • 2019-04-07
  • 2015-05-01
  • 2013-04-19
相关资源
最近更新 更多