0

I am using symmetric TripleDES encryption from the class TripleDESCryptoServiceProvider (.Net 2.0) to encrypt the contents of a file. The data gets encrypted perfectly but during decryption it throws the CryptographyException: Bad data


I am using key from current date time and IV from the randomly generated value by .Net class. Then I pass the same key and IV to the decryption method but it fails for some reason.
Here is my code :

static void Main(string[] args){
    string fileName = "input.exe";
    string newFileName = fileName + "crypted.exe";
    byte[] iv;
    var fileToEncrypt = File.ReadAllBytes(fileName);
    var encryptionKey = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(DateTime.Now.ToString("ddMMyyHmmss")));
    File.WriteAllBytes(newFileName, EncryptTripleDES(fileToEncrypt, encryptionKey, out iv));
    File.WriteAllBytes(fileName + "decrypted.exe", DecryptTripleDES(File.ReadAllBytes(newFileName), encryptionKey,iv));
}

public static byte[] EncryptTripleDES(byte[] dataToEncrypt, byte[] key, out byte[] iv){
    byte[] result;
    var tdes = new TripleDESCryptoServiceProvider { Key = key, KeySize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 };
    iv = tdes.IV;
    using(ICryptoTransform cTransform = tdes.CreateEncryptor()){
        result = cTransform.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
        tdes.Clear();
    }

    return result;
}

public static byte[] DecryptTripleDES(byte[] dataToDecrypt, byte[] key, byte[] iv){
    byte[] result;
    var tdes = new TripleDESCryptoServiceProvider { Key = key, KeySize = 128, Mode = CipherMode.CBC,IV = iv,Padding = PaddingMode.PKCS7 };

    using (ICryptoTransform cTransform = tdes.CreateDecryptor()){
        result = cTransform.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
        tdes.Clear();
    }

    return result;
}



UPDATE:
1. I have checked the value of IV being passed is valid and same as used in encryption.
2. Changing the padding to zero or none doesn't raise the exception but then the data isn't decrypted correctly. It comes out to be different than original.

8
  • Note, that 3DES is about the worst algorithm you can choose, and that an attacker can modify your encrypted data without you noticing. Commented Mar 15, 2014 at 11:57
  • Yes I know. Using it for some secret reason :) Commented Mar 15, 2014 at 12:14
  • Using the MD5 sum of the current time is also a bad practice. Keys should be generated from a cryptographically secure random number generator and filtered against DES weak keys. Commented Mar 15, 2014 at 12:24
  • Well thanks again but currently I am just interested in the solution, I'll handle the good practices later, and my use case is slightly different where all these things doesn't matter anyways Commented Mar 15, 2014 at 12:30
  • Check the returned IV of the EncryptTripleDES() function to make sure that the IV isn't being zeroed out by the Clear() function. If it is, you need to explicitly make a copy of the IV byte array at tdes. Commented Mar 15, 2014 at 12:31

1 Answer 1

1

The problem is in the way that you're constructing the TripleDESCryptoServiceProviders using an initializer. The Key is set first in the initializer, but then you set the KeySize, which causes the Key to be reset to a new (randomly generated) key, as a result, you're encrypting and decrypting with different keys (neither of which are the key you generate).

You can fix this by re-ordering the initializer so that KeySize is set first, or perhaps move the setting of the Key outside the initializer entirely to avoid any ambiguity:

public static byte[] EncryptTripleDES(byte[] dataToEncrypt, byte[] key, out byte[] iv){
    byte[] result;
    var tdes = new TripleDESCryptoServiceProvider { KeySize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 };
    // Key explicitly set here, not in the initializer:
    tdes.Key = key;
    iv = tdes.IV;

    using(ICryptoTransform cTransform = tdes.CreateEncryptor()){
        result = cTransform.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
        tdes.Clear();
    }

    return result;
}

public static byte[] DecryptTripleDES(byte[] dataToDecrypt, byte[] key, byte[] iv){
    byte[] result;
    var tdes = new TripleDESCryptoServiceProvider { KeySize = 128, Mode = CipherMode.CBC,IV = iv,Padding = PaddingMode.PKCS7 };
    // Key explicitly set here, not in the initializer:
    tdes.Key = key;

    using (ICryptoTransform cTransform = tdes.CreateDecryptor()){
        result = cTransform.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
        tdes.Clear();
    }

    return result;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Ohh my.. I could never have found that mistake. Difficult bug to find. But its working fine now, thanks a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.