繁体   English   中英

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

[英]C# Can't generate initialization vector IV

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

我要去哪里错了?

谢谢

MSDN明确声明

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

对于三重DES,它是64位。

初始化向量的大小必须与块大小匹配-如果是TripleDES,则为64位。 您的初始化向量比8个字节长得多。

此外,您实际上应该使用诸如PBKDF2之类的密钥派生功能从密码短语创建强密钥和初始化向量。

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

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

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

我已经在这里投票了所有答案(以及我之前的答案!),因为它们都是正确的。

但是,您正在犯一个更大的错误(我在v.early上犯了一个错误)-不要使用字符串来播种IV或密钥!

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

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

相反,您应该使用RNGCryptoServiceProvider初始化IV和密钥,并且,如果您需要为此捕获一个常量值以备将来使用,则仍应使用该类-但应将结果捕获为十六进制字符串或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;
}

可能有更好的方法可以做到这一点-但这对我有用。

我这样做是这样的:

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

IV使用算法本身通过LegalBlockSizes属性描述的块大小从派生字节'smusher'中获取字节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM