AESManaged文件加解密和前置初始化向量
本文关键字:初始化 向量 文件 解密 AESManaged | 更新日期: 2023-09-27 18:01:41
我正在尝试加密/解密字节-我已经使用System.Security.Cryptography中的AESManaged类做了很多关于AES算法的密钥和IV的阅读。我读了James Johnson对以下问题http://www.techques.com/question/1-7025135/My-Length-of-the-data-to-decrypt-is-invalid-error的回答,他建议您在加密例程中使用随机IV,并将IV添加到加密消息之前。解密函数从加密消息的开头去掉随机的IV来初始化解密类,然后解密其余的字节。我已经尝试在下面的代码中做到这一点。但是,当我在加密后尝试解密时,我一直得到"要解密的数据长度无效"的错误消息。有没有人能告诉我哪里出了问题?
USAGE: (streamToEncrypt/streamToDecrypt are System.IO.Stream)
using (var cryptoHelper = new AESHelper())
{
var encryptedBytes = cryptoHelper.Encrypt(AESHelper.StreamToByteArray(streamToEncrypt));
}
using (var cryptoHelper = new AESHelper())
{
var decryptedBytes = cryptoHelper.Decrypt(AESHelper.StreamToByteArray(streamToDecrypt));
}
public class AESHelper : IDisposable
{
public AesManaged AESManaged;
internal ICryptoTransform Encryptor { get; set; }
internal ICryptoTransform Decryptor { get; set; }
private const string KEY = "2428GD19569F9B2C2341839416C8E87G";
private static readonly byte[] Salt = Encoding.ASCII.GetBytes("?pt1$8f]l4g80");
private const Int32 ITERATIONS = 1042;
internal AESHelper()
{
AESManaged = new AesManaged();
AESManaged.BlockSize = AESManaged.LegalBlockSizes[0].MaxSize;
AESManaged.KeySize = AESManaged.LegalKeySizes[0].MaxSize;
AESManaged.Mode= CipherMode.CBC;
}
public void KeyGenerator()
{
var key = new Rfc2898DeriveBytes(KEY, Salt, ITERATIONS);
AESManaged.Key = key.GetBytes(AESManaged.KeySize / 8);
}
public byte[] Encrypt(byte[] input)
{
KeyGenerator();
var ms = new MemoryStream();
//Random IV
Encryptor = AESManaged.CreateEncryptor(AESManaged.Key, AESManaged.IV);
//Add the IV to the beginning of the memory stream
ms.Write(BitConverter.GetBytes(AESManaged.IV.Length), 0, sizeof(int));
ms.Write(AESManaged.IV, 0, AESManaged.IV.Length);
var cs = new CryptoStream(ms,
Encryptor, CryptoStreamMode.Write);
cs.Write(input, 0, input.Length);
cs.Close();
return ms.ToArray();
}
public byte[] Decrypt(byte[] input)
{
KeyGenerator();
// Get the initialization vector from the encrypted stream
var ms = new MemoryStream(input);
AESManaged.IV = ReadByteArray(ms);
Decryptor = AESManaged.CreateDecryptor(AESManaged.Key, AESManaged.IV);
var cs = new CryptoStream(ms,
Decryptor, CryptoStreamMode.Write);
cs.Write(input, 0, input.Length);
cs.Close();//Error occurs here
return ms.ToArray();
}
internal static byte[] ReadByteArray(Stream s)
{
var rawLength = new byte[sizeof(int)];
if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
{
throw new SystemException("Stream did not contain properly formatted byte array");
}
var buffer = new byte[16];
if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
{
throw new SystemException("Did not read byte array properly");
}
return buffer;
}
internal static byte[] StreamToByteArray(Stream inputStream)
{
if (!inputStream.CanRead)
{
throw new ArgumentException();
}
// This is optional
if (inputStream.CanSeek)
{
inputStream.Seek(0, SeekOrigin.Begin);
}
var output = new byte[inputStream.Length];
var bytesRead = inputStream.Read(output, 0, output.Length);
Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length");
return output;
}
public void Dispose()
{
if (AESManaged != null)
((IDisposable) AESManaged).Dispose();
}}
Many Thanks in advance
可能你已经解决了这个问题,但我只是把我的答案给其他人谁面临类似的问题。
由于input
数组中存在附加信息而发生错误。在public byte[] Encrypt(byte[] input)
方法中,您在写入加密数据之前写入IV长度和IV。行:
ms.Write(BitConverter.GetBytes(AESManaged.IV.Length), 0, sizeof(int));
ms.Write(AESManaged.IV, 0, AESManaged.IV.Length);
在public byte[] Decrypt(byte[] input)
方法中,您正在读取此信息并使用read IV作为AES算法的初始化向量。所有的罚款。然后你用CryptoStreamMode.Write
构造CryptoStream
,传递MemoryStream
对象ms
,得到解密数据。然而,传递的input
数组不仅包含加密消息,还包含您在加密过程中写入的IV。这就是它无法解密的原因。
要克服这个问题,您需要做的是从input
数组中提取密码数据并将其传递给:cs.Write(cipherData, 0, cipherData.Length);
或将模式更改为CryptoStreamMode.Read
并使用cs.Read(outputBuff, 0, outputBuff.Length);
。
也不要使用相同的MemoryStream
对象来读写,因为在CryptoStream
写入之后,它会有一些垃圾。