我有一组来自远程系统的用 TripleDES 编码的加密文档。我需要在 C# 中解码数据,我无法控制密钥或编码算法。我所拥有的只是密钥和模式(CBC)以及位于文件中的数据。
TripleDESCryptoServiceProvider 很容易使用,但我不知道如何在没有初始化向量的情况下使用 Decryptor。
我们有一个 24 字节(192 位)的密钥来解密,但没有别的。
string key = "1468697320656E6372797174696F6E206973737265206933";
byte[] keyData = ParseHex(key); // key is OK at 24 bytes
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.Mode = CipherMode.CBC;
des.GenerateIV();
var decryptor = des.CreateDecryptor(keyData,null); // des.IV
var encoded = File.ReadAllBytes(@"..\..\..\..\test.tdes");
byte[] output = decryptor.TransformFinalBlock(encoded, 0, encoded.Length);
这会因错误数据而彻底失败。如果我切换到 TransformBlock 代码至少会运行但只会产生乱码:
byte[] output = new byte[10000];
var count = decryptor.TransformBlock(encoded, 0, encoded.Length, output, 0);
所以问题是:
- 如果我只有一个密钥,是否需要 InitializationVector?
- 如果不是 null 是正确的传递吗?
- 除了键和模式之外,我还需要设置什么?
- 为什么 TransformBlock 至少可以工作而 TransformFinalBlock 只是失败了?
更新 - 发现问题
事实证明,解码问题不是由缺少初始化向量引起的,而是由加密数据提供者提供的不正确信息引起的。更新后的工作代码如下所示:
// Read the test data
byte[] encoded = File.ReadAllBytes(@"..\..\..\..\test.tdes");
// Get the key into a byte array
string key = "1468697320656E6372797174696F6E206973737265206933";
byte[] keyData = ParseHex(key);
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.Mode = CipherMode.ECB; // Make sure this is correct!!!
des.Padding = PaddingMode.Zeros; // Make sure this is correct!!!
des.Key = keyData;
var decryptor = des.CreateDecryptor();
byte[] output = decryptor.TransformFinalBlock(encoded, 0, encoded.Length);
string dataString = Encoding.Default.GetString(encoded);
Console.WriteLine(dataString);
Console.WriteLine("\r\n\r\nDecoded:");
string result = Encoding.Default.GetString(output);
Console.WriteLine(result);
Console.Read();
在我们的案例中,关键是使用正确的 CipherMode 和 Padding。修复填充使 TransformFinalBlock() 工作没有坏数据错误。修复 CipherMode 可以正确解密数据。
故事的寓意:在 CipherMode.ECB 模式下,至少有一个初始化向量,您不需要提供初始化向量。如果没有提供 IV,提供商将自动生成一个,但解密仍然有效(至少使用 ECB)。
最后,确保您拥有来自加密数据的提供商的所有信息至关重要。