C#无法生成初始化向量IV

时间:2010-07-05 12:03:42

标签: c# cryptography encryption initialization-vector

当我尝试为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)与此算法的块大小不匹配。

我哪里错了?

谢谢

6 个答案:

答案 0 :(得分:10)

MSDN明确states

  

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

对于Triple DES,它是64位。

答案 1 :(得分:6)

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

此外,您应该使用密钥派生函数(如PBKDF2)从密码短语创建强密钥和初始化向量。

答案 2 :(得分:5)

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

答案 3 :(得分:5)

密钥应为24字节,IV应为8字节。

tripDES.Key = Encoding.ASCII.GetBytes("123456789012345678901234");
tripDES.IV = Encoding.ASCII.GetBytes("12345678");

答案 4 :(得分:4)

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

然而,你犯的是一个更大的错误(我也做了一个错误) - 不要使用一个字符串来制作IV或KEY !!!

编译时字符串文字是一个unicode字符串,尽管你不会得到一个随机或足够宽的字节值扩展(因为即使一个随机字符串包含大量的重复字节,因为它很窄可打印字符的字节范围),很容易得到一个实际上需要2个字节而不是1个字符的字符 - 尝试使用键盘上一些更奇特的字符中的8个,你会看到我的意思 - 转换为字节时你最终可能超过8个字节。

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

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

为了简单地实现这一点,我编写了一个我在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;
}

这样做可能有更好的方法 - 但它对我有用。

答案 5 :(得分:0)

我这样做:

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

IV使用块大小从导出字节'smusher'获取字节,如算法本身通过LegalBlockSizes属性所描述的那样。