C# Aes byte[] Encrypt/Decrypt : 不是一个完整的块



我收到错误"输入数据不是一个完整的块",我不知道我的代码是错误的还是缺少什么。 我尝试加密/解密相同长度的字节。

=byte[] plain => MyEnc(plain( => byte[] encrypted =>MyDec(encrypt( => byte[] plain

纯文本和加密具有相同的长度。

这是我的加密代码:

public static byte[] MyEnc(byte[] Input)
{
byte[] inputencdec = Input;
byte[] encrypted;
using (MemoryStream mstream = new MemoryStream())
{
using (AesCryptoServiceProvider encdec = new AesCryptoServiceProvider())
{
encdec.BlockSize = 128;
encdec.KeySize = 256;
encdec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
encdec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
ICryptoTransform icrypt = encdec.CreateEncryptor(encdec.Key, encdec.IV);
using (CryptoStream cryptoStream = new CryptoStream(mstream,
icrypt, CryptoStreamMode.Write))
{
cryptoStream.Write(inputencdec, 0, inputencdec.Length);
}
}
encrypted = mstream.ToArray();
}
return encrypted;
}

这是我的解密代码:

public static byte[] MyDec(byte[] Input)
{
byte[] inputencdec = Input;
byte[] buffer = new byte[Input.Length];
int totalRead = 0;
byte[] plain;
MemoryStream plainStream = new MemoryStream();
using (MemoryStream mStream = new MemoryStream(inputencdec))
{
using (AesCryptoServiceProvider encdec = new AesCryptoServiceProvider())
{
encdec.BlockSize = 128;
encdec.KeySize = 256;
encdec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
encdec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
ICryptoTransform icrypt = encdec.CreateDecryptor(encdec.Key, encdec.IV);
using (CryptoStream cryptoStream = new CryptoStream(mStream, icrypt, CryptoStreamMode.Read))
{
while (true)
{
int read = cryptoStream.Read(buffer, 0, inputencdec.Length);
if (read == 0)
break;
else
plainStream.Write(buffer, totalRead, read);
totalRead += read;
}
}
}
plain = plainStream.ToArray();
}
return plain;
}

对于您正在使用的 CBC 模式加密,纯文本和加密长度不同。明文需要先填充,然后才能加密,因此密文大小始终大于 CBC 的明文消息(这是解密器使用的默认模式(。

流式处理模式不需要扩展密文,因为它们不需要填充。不幸的是,Microsoft选择不在 .NET 中包含计数器模式。您可以使用 CFB 模式。

如果您需要并行加密,您也可以决定使用 ECB实现计数器模式(在问题下方的评论中(。一般来说,AES现在非常快,不需要并行性。与创建多线程代码相比,实现静态大小的计数器和 CTR 缓冲区应该相形见绌。


这是不正确的,可能会导致问题:

int read = cryptoStream.Read(buffer, 0, inputencdec.Length);

你当然应该输入buffer.length,而不是inputencdec.length。缓冲区的用途是将数据存储在缓冲区中,方法是每次循环迭代最多读取buffer.length个字节。

这也是不正确的:

plainStream.Write(buffer, totalRead, read);

问题是totalRead应该是buffer中的偏移量,而不是流中的偏移量。您正在读取缓冲区的偏移量 0,因此您也应该从偏移量 0 开始写入。


您还可以为明文创建一个MemoryStream,使用解密器用CryptoStream包装它,然后一次性写入密文。据我所知,加密/解密不需要使用不同的方案。无论如何,您似乎将所有明文/密文都保存在内存中。


笔记:

  • 对于CBC模式,IV应该是随机的;它通常以密文为前缀,并由解密器删除和使用;
  • 键和 IV 应该由随机字节组成;它们不应该是字符串。

相关内容

最新更新