在SO和msdn上找到一些AES C#包装器时(最值得注意的是here和here和here)我写了下面的代码,我犯了写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);
}
}
}