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

时间:2014-04-05 01:03:38

标签: c# security aes

我从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值?

2 个答案:

答案 0 :(得分:1)

Ruby和C#字符串不同,因此您的C#IV会在其中添加额外的字节。

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

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

如果您需要可打印的表单,可以对IV进行base-64编码。或者你可以用C#编写一个字节数组文字:

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

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

答案 1 :(得分:0)

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

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

编辑:看起来Ruby默认使用PKCS5似乎是here,所以只需在C#中设置填充,看看会发生什么。

aes.Padding = PaddingMode.PKCS5;

在将数据交给算法之前,还要尝试对数据进行base64编码,然后对解密方法中获得的数据进行base64解码。我也必须这样做,否则来自解密的数据有时会被破坏。

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