1

当我尝试为 TripleDES 加密器创建 IV 初始化向量时,出现以下错误。

请看代码示例:

TripleDESCryptoServiceProvider tripDES = new TripleDESCryptoServiceProvider();

byte[] key = Encoding.ASCII.GetBytes("SomeKey132123ABC");
byte[] v4 = key;
byte[] connectionString = Encoding.ASCII.GetBytes("SomeConnectionStringValue");
byte[] encryptedConnectionString = Encoding.ASCII.GetBytes("");

// Read the key and convert it to byte stream
tripDES.Key = key; 
tripDES.IV = v4;

这是我从 VS 得到的例外。

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

我哪里错了?

谢谢

4

6 回答 6

10

MSDN 明确指出

... IV 属性的大小必须与 BlockSize 属性相同。

对于三重 DES,它是 64 位。

于 2010-07-05T12:06:26.357 回答
6

初始化向量的大小必须与块大小匹配——在 TripleDES 的情况下为 64 位。您的初始化向量比八个字节长得多。

此外,您应该真正使用像PBKDF2这样的密钥派生函数来从密码短语创建强密钥和初始化向量。

于 2010-07-05T12:08:17.740 回答
5

IV 的长度(以位为单位)必须与tripDES.BlockSize. 对于 TripleDES,这将是 8 个字节(64 位)。

于 2010-07-05T12:06:03.197 回答
5

密钥应该是 24 字节,IV 应该是 8 字节。

tripDES.Key = Encoding.ASCII.GetBytes("123456789012345678901234");
tripDES.IV = Encoding.ASCII.GetBytes("12345678");
于 2010-07-05T12:07:37.133 回答
4

我已经投票赞成每个答案(以及那些在我之前的答案!),因为它们都是正确的。

但是,您犯了一个更大的错误(我也很早就犯了这个错误)-不要使用字符串来播种 IV 或密钥!!!

编译时字符串文字是 unicode 字符串,尽管您不会获得随机或足够广泛的字节值分布(因为即使是随机字符串也包含大量重复字节,因为可打印字符),很容易得到一个实际上需要 2 个字节而不是 1 个字节的字符 - 尝试在键盘上使用 8 个更奇特的字符,你会明白我的意思 - 当转换为字节时,你可以结束超过 8 个字节。

好的 - 所以你正在使用 ASCII 编码 - 但这并不能解决非随机问题。

相反,您应该使用 RNGCryptoServiceProvider 来初始化您的 IV 和 Key,如果您需要为此捕获一个常量值以供将来使用,那么您仍然应该使用该类 - 但将结果捕获为十六进制字符串或 Base-64 编码值(不过,我更喜欢十六进制)。

为了简单地实现这一点,我编写了一个在 VS 中使用的宏(绑定到键盘快捷键CTRL+SHIFT+G、CTRL+SHIFT+H),它使用 .Net PRNG 来生成一个十六进制字符串:

Public Sub GenerateHexKey()
  Dim result As String = InputBox("How many bits?", "Key Generator", 128)

  Dim len As Int32 = 128

  If String.IsNullOrEmpty(result) Then Return

  If System.Int32.TryParse(result, len) = False Then
      Return
  End If

  Dim oldCursor As Cursor = Cursor.Current

  Cursor.Current = Cursors.WaitCursor

  Dim buff((len / 8) - 1) As Byte
  Dim rng As New System.Security.Cryptography.RNGCryptoServiceProvider()

  rng.GetBytes(buff)

  Dim sb As New StringBuilder(CType((len / 8) * 2, Integer))
  For Each b In buff
      sb.AppendFormat("{0:X2}", b)
  Next

  Dim selection As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
  Dim editPoint As EnvDTE.EditPoint

  selection.Insert(sb.ToString())
  Cursor.Current = oldCursor
End Sub

现在您需要做的就是将您的十六进制字符串文字转换为字节数组 - 我使用一种有用的扩展方法来做到这一点:

public static byte[] FromHexString(this string str)
{
  //null check a good idea
  int NumberChars = str.Length;
  byte[] bytes = new byte[NumberChars / 2];
  for (int i = 0; i < NumberChars; i += 2)
    bytes[i / 2] = Convert.ToByte(str.Substring(i, 2), 16);
  return bytes;
}

可能有更好的方法来做这件事——但它对我有用。

于 2010-07-05T12:25:44.433 回答
0

我这样做:

var derivedForIv = new Rfc2898DeriveBytes(passwordBytes, _saltBytes, 3);
_encryptionAlgorithm.IV = derivedForIv.GetBytes(_encryptionAlgorithm.LegalBlockSizes[0].MaxSize / 8);

The IV gets bytes from the derive bytes 'smusher' using the block size as described by the algorithm itself via the LegalBlockSizes property.

于 2012-03-22T22:38:15.317 回答