没有初始化向量的C# TripleDES提供程序?

8
我有一组使用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);

这会直接导致 Bad data 错误。如果我切换到 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()能够正常工作,而不会出现“Bad Data”错误。修复CipherMode可以正确地解密数据。
故事的寓意:在CipherMode.ECB模式下,至少不需要提供初始化向量。如果没有提供IV,则提供程序将自动生成一个,但解密仍然有效(至少在ECB模式下)。
最重要的是确保您从加密数据的提供程序那里获得了所有信息。

由于它确实是ECB模式,因此不需要IV,即使您提供了一个也不会使用。 - Sani Huttunen
1个回答

9

尝试回答每个问题:

  • CBC模式需要初始化向量。它不需要保密(不像密钥),因此应该从远程系统发送。
  • 由于需要使用IV,所以空值不是正确的传递方式。
  • 填充模式。您需要知道使用了哪种填充模式。
  • TransformFinalBlock可能会失败,因为填充模式错误。

编辑

ECB(电子密码本)和CBC(密码分组链接)之间的区别如下图所示:

ECB Mode

CBC Mode

如您所见,在ECB模式中没有使用IV。因此,即使提供了IV,它也将被忽略。


1
Sani,谢谢!你指引了我正确的方向。填充起到了消除坏数据问题(零)的作用。我还开始尝试不同于提供者所说的密码模式,发现ECB可行。真糟糕,这都是因为提供者给了我们错误的信息 :-) - Rick Strahl
1
很好,你解决了它。正如你在编辑中所述,拥有所有正确的信息非常关键:加密算法、加密模式、填充模式和(如果加密模式要求)初始向量(IV)。离题:Maui Rick Strahl? - Sani Huttunen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接