简体   繁体   English

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

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

I get the following error when I try to create a IV initialization vector for TripleDES encryptor. 尝试为TripleDES加密器创建IV初始化向量时,出现以下错误。

Please see the code example: 请参见代码示例:

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;

This is the exception that I get from the VS. 这是我从VS获得的例外。

Specified initialization vector (IV) does not match the block size for this algorithm. 指定的初始化向量(IV)与该算法的块大小不匹配。

Where am I going wrong? 我要去哪里错了?

Thank you 谢谢

MSDN explicitly states that: MSDN明确声明

...The size of the IV property must be the same as the BlockSize property. ... IV属性的大小必须与BlockSize属性相同。

For Triple DES it is 64 bits. 对于三重DES,它是64位。

The size of the initialization vector must match the block size - 64 bit in case of TripleDES. 初始化向量的大小必须与块大小匹配-如果是TripleDES,则为64位。 Your initialization vector is much longer than eight bytes. 您的初始化向量比8个字节长得多。

Further you should really use a key derivation function like PBKDF2 to create strong keys and initialization vectors from password phrases. 此外,您实际上应该使用诸如PBKDF2之类的密钥派生功能从密码短语创建强密钥和初始化向量。

The IV must be the same length (in bits) as tripDES.BlockSize . IV必须与tripDES.BlockSize相同的长度(以位为tripDES.BlockSize This will be 8 bytes (64 bits) for TripleDES. 对于TripleDES,这将是8个字节(64位)。

Key should be 24 bytes and IV should be 8 bytes. 密钥应为24个字节,IV应为8个字节。

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

I've upvoted every answer (well the ones that are here before mine!) here as they're all correct. 我已经在这里投票了所有答案(以及我之前的答案!),因为它们都是正确的。

However there's a bigger mistake you're making (one which I also made v.early on) - DO NOT USE A STRING TO SEED THE IV OR KEY!!! 但是,您正在犯一个更大的错误(我在v.early上犯了一个错误)-不要使用字符串来播种IV或密钥!

A compile-time string literal is a unicode string and, despite the fact that you will not be getting either a random or wide-enough spread of byte values (because even a random string contains lots of repeating bytes due to the narrow byte range of printable characters), it's very easy to get a character which actually requires 2 bytes instead of 1 - try using 8 of some of the more exotic characters on the keyboard and you'll see what I mean - when converted to bytes you can end up with more than 8 bytes. 编译时字符串文字是unicode字符串,尽管事实上您不会得到随机的或足够宽的字节值扩展(因为即使随机字符串也包含很多重复的字节,这是因为它的字节范围很窄), ,实际上得到一个需要2个字节而不是1个字节的字符非常容易-尝试在键盘上使用一些更奇特的字符中的8个,您会明白我的意思-当转换为字节时,您最终可以超过8个字节。

Okay - so you're using ASCII Encoding - but that doesn't solve the non-random problem. 好的-您正在使用ASCII编码-但这不能解决非随机问题。

Instead you should use RNGCryptoServiceProvider to initialise your IV and Key and, if you need to capture a constant value for this for future use, then you should still use that class - but capture the result as a hex string or Base-64 encoded value (I prefer hex, though). 相反,您应该使用RNGCryptoServiceProvider初始化IV和密钥,并且,如果您需要为此捕获一个常量值以备将来使用,则仍应使用该类-但应将结果捕获为十六进制字符串或Base-64编码值(我更喜欢十六进制)。

To achieve this simply, I've written a macro that I use in VS (bound to the keyboard shortcut CTRL+SHIFT+G, CTRL+SHIFT+H ) which uses the .Net PRNG to produce a hex string: 为了简单地实现此目的,我编写了一个在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

Now all you need to do is to turn your hex string literal into a byte array - I do this with a helpful extension method: 现在您需要做的就是将十六进制字符串文字转换为字节数组-我使用一种有用的扩展方法来做到这一点:

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;
}

There are probably better ways of doing that bit - but it works for me. 可能有更好的方法可以做到这一点-但这对我有用。

I do it like this: 我这样做是这样的:

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. IV使用算法本身通过LegalBlockSizes属性描述的块大小从派生字节'smusher'中获取字节。

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

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