I have a set of encrypted documents encoded using TripleDES coming from a remote system. I need to decode the data in C #, and I do not control the key or encoding algorithm. All I have is the key and mode (CBC), as well as the data in the file.
TripleDESCryptoServiceProvider is simple enough to use, but I cannot figure out how to use Decryptor without an initialization vector.
We have a 24-byte (192-bit) decryption key, 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 does not work with bad data. If I switch to TransformBlock, the code will at least work, but will only produce 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 an InitializationVector required?
- If not null, then the right thing should go through?
- What else would I need to install behind the key and mode?
- Why does TransformBlock work at least and TransformFinalBlock just doesn't work?
Update - Problem Found
It turns out that the decoding problem was caused not by the missing initialization vector, but by incorrect information from the encrypted data provider. The updated working code is as follows:
// 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 to use the correct CipherMode and Padding. Locking the pad made TransformFinalBlock () work without Bad Data errors. Committing CipherMode made correctly unencrypted data.
The moral of the story: in CipherMode.ECB mode, at least the initialization vector you do not need to provide the initialization vector. If there is no IV, the provider will automatically generate one, but decryption still works (at least with ECB).
In the end, CRUCIAL, to make sure that you have all the information from the provider who encrypted the data.