TripleDES TransformFinalBlock occasionally giving 'Bad Data. ' error

486 views Asked by At

I have the following code:

public static string PerformEncryption(string text, string uniqueKey, bool encrypt = false)
{
   byte[] textBytes = encrypt ? Encoding.UTF8.GetBytes(text) :  Convert.FromBase64String(text);
   byte[] resultArray;
   var staticKey = Convert.FromBase64String(ConfigReader.SecretKey);
   using (TripleDESCryptoServiceProvider tDes = new TripleDESCryptoServiceProvider())
   {
       tDes.Mode = CipherMode.ECB;
       tDes.Padding = PaddingMode.PKCS7;
       tDes.Key = GenerateTripleDesKey(uniqueKey, staticKey);     
       CTransform = encrypt ? tDes.CreateEncryptor() : tDes.CreateDecryptor();
       resultArray = CTransform.TransformFinalBlock(textBytes, 0, textBytes.Length);
       tDes.Clear();
   }
   if (encrypt)
       return Convert.ToBase64String(resultArray, 0, resultArray.Length);

   return Encoding.UTF8.GetString(resultArray); 
}



private static byte[] GenerateTripleDesKey(string uniqueKey, byte[] staticKey)
{
   byte[] keyArray;
   using (SHA512CryptoServiceProvider hash = new SHA512CryptoServiceProvider())
      keyArray = hash.ComputeHash(Encoding.UTF8.GetBytes(string.Format("{0}{1}", uniqueKey, staticKey)));

   byte[] trimmedBytes = new byte[24];
   Buffer.BlockCopy(keyArray, 0, trimmedBytes, 0, 24);
   return trimmedBytes;
}

 

PerformEncryption is used as a helper method to perform encryption/decryption of a string. A secret key is also supplied for either operation.

It is used in a web API application that is consumed by a mobile app in Android & iOS devices.

Bad Data error is occurring with large portion of the users that are on Android, with a much smaller occurance of this error on iOS. Any tests I have conducted on similar mobile devices do not produce the issue.

Only way I can reproduce error is if I modify the string value in a unit test after its encrypted.

The web API uses Async/Await so I'm not sure if this has something to do with it?

Is there anything I miss with the code above that I have left out or is bad practice?

I don't have access to the raw request being sent to the server so I can't determine if the encrypted value has its content appended with dodgy characters from Android/iOS in the request??

My other thoughts are:
should I switch from using UTF8 getbytes() to ASCII equivalent helper class if that is causing issues with iOS and android environments

Should I just switch to using a diff algorithm completely like AES.

1

There are 1 answers

0
zaph On
  1. 3DES should not be used for new code, instead use AES.

  2. Do not use ECB mode, it is insecure, see ECB mode, scroll down to the Penguin. Instead use CBC mode with a random IV, just prefix the encrypted data with the IV for use in decryption.

  3. PBKDF2 is more secure than a simple hash or even a salted hash. The main difference is iteration in order to take more time to calculate the key,100,000 iterations is common for PBKDF2.

  4. UTF-8 is to be preferred over ASCII which is too limited.