[英]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 谢谢
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.