用 aes 加密后我的文件长了一个块

after encrypting with aes my file is one block longer

我正在使用 AES 加密模式 CBC 和默认填充(我没有设置它,所以我猜它会设置默认填充模式)。

当我尝试以 example/test 的身份加密一个 .txt 文件时,只写了几个字(将其视为 50 个字节);输出文件高出一个块,因此,例如 4096+16=5012。我猜这是因为它读取了一个完整的 4096 字节块,对其进行编码并写入。但是后来他添加了 16 个额外的字节,不知道为什么;因为填充应该填充一个块。

我的代码是:

using (Aes myAes = Aes.Create())
{

     myAes.BlockSize = myAes.LegalBlockSizes[0].MaxSize;
     myAes.KeySize = myAes.LegalKeySizes[0].MaxSize;
     myAes.Mode = CipherMode.CBC;
     myAes.GenerateIV();
     myAes.GenerateKey();
     ICryptoTransform encryptor = myAes.CreateEncryptor(myAes.Key, myAes.IV );
     CryptoStream csCrypt = new CryptoStream(FileOUT, encryptor, CryptoStreamMode.Write);

     do
     {
          bytesRead = FileIN.Read(buffer, 0, bufferLen);
          if (bytesRead != 0)
          {
               csCrypt.Write(buffer, 0, bufferLen);
          }
     } while (bytesRead != 0);

     csCrypt.Close();
     csCrypt.Dispose();
     FileIN.Close();
     FileIN.Dispose();
     FileOUT.Close();
     FileOUT.Dispose();
}

是吗?有什么方法可以修复添加的 16 个额外字节吗?

具有 CBC 或 ECB 等操作模式的 AES 仅适用于完整块(16 字节的倍数),这就是需要填充的原因。当明文已经是块大小的倍数时,则必须添加额外的填充块,否则你不知道解密后要删除多少字节。

由于 4096 字节是块大小的倍数,因此添加了一个完整的填充块,然后对所有内容进行加密,得到 5012 个密文字节。

这就是 PKCS#7 填充的运作方式(有时称为 PKCS#5 填充)。如果你能确定你总是读取块大小的倍数的字节,那么你可以设置

myAes.Padding = PaddingMode.None;

用于加密和解密。

由于您使用的是带有随机生成的 IV 的 CBC 模式,因此您需要将其存储在某个地方。将 IV 写在密文的开头通常是个好主意,这样您就不必通过其他方式跟踪它。不一定要保密,只要不可预测即可。