C# TripleDES Provider without an Initialization Vector?
Asked Answered
R

1

8

I have a set of encrypted documents encoded with TripleDES coming from a remote system. I need to decode the data in C# and I have no control over the key or encoding algorithm. All I have is the key and the mode (CBC) and the data located in a file.

The TripleDESCryptoServiceProvider is easy enough to use, but I can't figure out how to use the Decryptor without an Initialization Vector.

We have a have 24 byte (192bit) key to decrypt with, but nothing else.

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

This fails outright with Bad data. If I switch to TransformBlock the code at least runs but produces just gibberish:

   byte[] output = new byte[10000];
   var count = decryptor.TransformBlock(encoded, 0, encoded.Length, output, 0);

So the questions are:

  • If I only have a key is the InitializationVector required?
  • If not is null the right thing to pass?
  • What else would I possibly need to set beyond the key and mode?
  • Why does TransformBlock at least work and TransformFinalBlock just fails?

Update - found the problem

It turns out the decoding problem was caused, not by the missing Initialization Vector, but by incorrect information from the provider of the encrypted data. The updated working code looks like this:

        // 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();

The key in our case was using the proper CipherMode and Padding. Fixing the padding made TransformFinalBlock() work without Bad Data errors. Fixing the CipherMode made properly unencrypted the data.

Moral of the story: In CipherMode.ECB mode at least an Initialization Vector you don't need to provide an initialization vector. If no IV is provided the provider will auto-generate one, but the decryption still works (at least with ECB).

In the end it's CRUCIAL to make sure you have all the information from the provider that encrypted the data.

Romonaromonda answered 20/9, 2012 at 23:7 Comment(1)
Since it really was ECB mode, no IV is necessary and even if you provide one it is not used.Dan
D
9

Trying to answer each point:

  • The Initialization Vector is required in CBC mode. It is not required to be a secret (unlike the key) so it should be sent from the remote system.
  • Since you need the IV, null is not the right thing to pass.
  • Padding mode. You need to know which padding mode is used.
  • TransformFinalBlock probably fails because the Padding mode is wrong.

Edit

The difference between ECB (Electronic Code Book) and CBC (Cipher Block Chaining) is illustrated below:

ECB Mode

CBC Mode

As you can see no IV is used in ECB mode. So even if you provide one it will be ignored.

Dan answered 20/9, 2012 at 23:27 Comment(2)
Sani thanks! You pointed me in the right direction here. The padding worked to get rid of the bad data problem (Zeros). I also started experimenting with different cipher modes than what the provider said it was in, and I found that ECB worked. Crap all this because the provider gave us incorrect information :-)Romonaromonda
Good that you solved it. As you stated in your edit, it is crucial to have all the correct information: Encryption algorithm, Encryption mode, Padding mode and, if the Encryption mode demands, the IV. Off topic: Maui Rick Strahl?Dan

© 2022 - 2024 — McMap. All rights reserved.