为什么这个AES代码产生相同的加密输出?

时间:2016-11-17 01:43:11

标签: c# aes

在SO和msdn上找到一些AES C#包装器时(最值得注意的是hereherehere)我写了下面的代码,我犯了写IV的错误到CryptoStream。

我注意到,当IV写入CryptoStream时,输出字节数组包含相同的值。如果我注释掉cryptoStream.Write(aes.IV, 0, aes.IV.Length);行,那很好,输出会有所不同。

我的问题是为什么在这种情况下输出是一样的?我意识到将IV写入CryptoStream并不是我应该做的,但我发现它很奇怪,特别是因为每次函数执行时IV都不同。

TestEncryption.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
  public class TestEncryption
  {

    public static readonly int KeyBitSize = 256;

    private static readonly int BlockBitSize = 128;
    public static readonly byte[] _salt = new byte[] { 23, 13, 23, 213, 15, 193, 134, 147, 223, 151 };
    const int Iterations = 10000;


    public static string Encrypt(byte[] inputBytes, string password)
    {

      using (var aes = new AesManaged

      {
        KeySize = KeyBitSize,
        BlockSize = BlockBitSize,
        Mode = CipherMode.CBC,
        Padding = PaddingMode.PKCS7,
      })
      {
        var cryptKey = CreateKey(password);
        aes.GenerateIV();
        Console.WriteLine("IV={0}", string.Join(", ", aes.IV.Select(b => b.ToString())));
        using (var encrypter = aes.CreateEncryptor(cryptKey, aes.IV))
        using (var output = new MemoryStream())
        {
          using (var cryptoStream = new CryptoStream(output, encrypter, CryptoStreamMode.Write))
          {
            cryptoStream.Write(aes.IV, 0, aes.IV.Length);
            cryptoStream.Write(inputBytes, 0, inputBytes.Length);
            cryptoStream.FlushFinalBlock();
          }
          Console.WriteLine("Output={0}", string.Join(", ", output.ToArray().Select(b => b.ToString())));
          return Convert.ToBase64String(output.ToArray());
        }

      }
    }
    public static string Encrypt(string input, string password)
    {
      return Encrypt(Encoding.UTF8.GetBytes(input), password);
    }


    public static byte[] CreateKey(string password)
    {

      using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, _salt, Iterations))
        return rfc2898DeriveBytes.GetBytes(32);
    }
  }
}

Program.cs的

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
  class Program
  {
    static void Main(string[] args)
    { 
      //Test1();

      Test2();
      Console.ReadLine();
    }

    private static void Test2()
    {

      string text = "some longer text";
      string pwd = "test2";

      String encrypt1 = TestEncryption.Encrypt(text, pwd);
      String encrypt2 = TestEncryption.Encrypt(text, pwd);

      Console.WriteLine(encrypt1 == encrypt2);
    }
 }

}

0 个答案:

没有答案