Michael Nee
Michael Nee

Reputation: 29

C# Triple DES in ECB Decrypt Issues

I have this PHP script which we need to convert to C# to decode a result from an API post request, but I am experiencing issues with my C# implementation.

We get the result fine while running the PHP script which is XXXX-XXXX-XXXX but get different errors.

Values are:

encodedText = "U8Q+m2zpFMLa/3gYILHx5w=="
key = "examplesecret"
keyHash = "6315046b2c085bbeeab87c65"

Php Script:

<?php
$secret = 'examplesecret';
$encrypted_code = 'U8Q+m2zpFMLa/3gYILHx5w==';
// Base64
// Decode
$encrypted_code = base64_decode( $encrypted_code );
// Create decryption module
$cipher = mcrypt_module_open( 'tripledes', '', 'ecb', '' );
$keysize = mcrypt_enc_get_key_size( $cipher ); // = 24
// Generate key
$hash = md5( $secret );
$key = substr( $hash, 0, $keysize );
// Initialise decrypter
$iv = mcrypt_create_iv( mcrypt_enc_get_iv_size( $cipher ),
MCRYPT_DEV_RANDOM );
mcrypt_generic_init( $cipher, $key, $iv );
// Decrypt code
$decrypted = mdecrypt_generic( $cipher, $encrypted_code );
// Output decrypted code
echo $decrypted;
?>

C# Script

public static string Decrypt(string encodedText, string key)
{
    TripleDESCryptoServiceProvider desCryptoProvider = new TripleDESCryptoServiceProvider();
    MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();

    byte[] byteHash;
    byte[] byteBuff;

    byteHash = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(key));
    desCryptoProvider.Key = byteHash;
    desCryptoProvider.Padding = PaddingMode.None;
    desCryptoProvider.Mode = CipherMode.ECB; //CBC, CFB
    byteBuff = Convert.FromBase64String(encodedText);

    var byteHex = BitConverter.ToString(byteBuff).Replace("-", " ");

    string plaintext = Encoding.UTF8.GetString(desCryptoProvider.CreateDecryptor().TransformFinalBlock(byteHex, 0, byteHex.Length));
    return plaintext;
}

Upvotes: 0

Views: 673

Answers (1)

bartonjs
bartonjs

Reputation: 33088

A couple of things I see:

  1. You derive $key via a substr in PHP; but just take the output of MD5 in C#, are they the same? (e.g. if PHP's value was a hex string, then the 16 bytes of MD5 are 32 characters, which gets trunctated to 24 characters, being a 12-byte (96-bit) value; in C# it's 16 bytes)
  2. Speaking of the keys, if you're using PHP before 5.6, a deficient key was 0-padded (per the documentation of mcrypt_encrypt; C# won't do that for you. So that's another thing to check.
  3. You have an IV in the PHP code, but ECB doesn't use an IV. That won't be causing your problem here, but it's less than ideal.
  4. Of course, I should at this point warn that ECB is "too stable" and doesn't hide patterns in encrypted data, and doesn't hide that you're sending the same message again.
  5. TransformFinalBlock takes bytes, but you seem to be giving it a string here. Since C# is a strongly typed language, this can't really be the code you're running.
  6. You should avoid talking about the specific implementations of algorithms. TripleDES.Create() is preferred to new TripleDESCryptoServiceProvider(), MD5.Create() over new MD5CryptoServiceProvider(); and type the variables as just TripleDES and MD5.
  7. The TripleDES object, the MD5 object, and the output of CreateDecryptor() are all IDisposable, so you should really wrap them in a using statement to be more efficient with your native resources.

The most likely culprit for your problem, though, is that you're not generating the same key in both languages.

Upvotes: 2

Related Questions