指定的初始化向量 (IV) 与使用 AES 的 c# 中的块大小不匹配

本文关键字:AES 不匹配 向量 初始化 IV | 更新日期: 2023-09-27 17:56:39

我从Ruby中提供的示例开始:

cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.encrypt
cipher.key = "wB'x14='r'xC3'xC1'x84$'x10'xCE'xC0'x10'x03'xFE'x18"
cipher.iv = "'xD8a'"'xFAs'xBD'xE4'xF9'xA4'xA1'x1E'xA5l'xA6@'xFD"

并尝试在 c# 中复制:

string AesKey = "wB'x14='r'xC3'xC1'x84$'x10'xCE'xC0'x10'x03'xFE'x18";
string AesIV = "'xD8a'"'xFAs'xBD'xE4'xF9'xA4'xA1'x1E'xA5l'xA6@'xFD";
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 128;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
aes.Mode = CipherMode.CBC;
byte[] src = Encoding.Unicode.GetBytes(text);
using (ICryptoTransform encrypt = aes.CreateEncryptor())
  {
      byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
      string EncryptedResult = Convert.ToBase64String(dest);
      EncryptedValue.Text = EncryptedResult;
  }

我收到错误:

"指定的初始化向量 (IV) 与此算法的块大小不匹配。"

我是否误解了我未能解释的原始键和 iv 值的格式?

指定的初始化向量 (IV) 与使用 AES 的 c# 中的块大小不匹配

Ruby 和 C# 字符串是不同的,因此您的 C# IV 最终会包含额外的字节。

在 Ruby 中,字符串实际上只是一个字节序列。每个'x后跟两个十六进制数字。因此,'xD8a实际上是字节0xD8 0x61的文本表示形式。将此"字符串"用作初始化向量时,不需要字符编码;它已经是一个伪装成文本的字节序列。

在 C# 中,字符串是字符序列。要将字符串转换为字节数组,请使用字符编码 — 在本例中选择了 UTF-8。为了表示数百万个不同的字符,在 C# 中,每个'x转义后跟 1 到 4 个十六进制数字。因此,例如,子字符串'xD8a不表示两个字节,而是表示单个字符 (U+0D8A),当您使用 UTF-8 对其进行编码时,它会转换为 3 字节序列0xE0 0xB6 0x8A而不是 Ruby 等效0xD8 0x61双字节序列。

如果您需要可打印的表格,您可以对 IV 进行 base-64 编码。或者,您可以在 C# 中将其编写为字节数组文本:

aes.IV = new byte[] { 0xD8, 0x61, ... };

但是,这一点可能没有实际意义,因为实际应用程序需要安全性,而硬编码的IV并不安全。

确保使用相同的填充技术,例如 PKCS5 填充或纯零。几周前,我在 php/java/c# 中遇到了这个问题,是填充导致了这个问题。

数据存储在块中,最后一个块通常不会是其他块的确切大小,因此它必须填充其末尾以使其成为正确的块大小。在 C# 中,您可以轻松设置它,但在 ruby 中,您可能需要自己编写代码来附加填充。

编辑:看起来Ruby可能默认使用PKCS5,因为它似乎在这里,所以只需在C#中设置填充,看看会发生什么。

aes.Padding = PaddingMode.PKCS5;

在将数据交给算法之前,还可以尝试对数据进行 base64 编码,然后对从 decrypt 方法获取的数据进行 base64 解码。我也必须这样做,否则解密中的数据有时会损坏。

我还建议使用 256 位密钥,因为它更安全,并且与 128 位密钥一样易于使用。