Shane Chin
Shane Chin

Reputation: 576

C# and PHP encryption/decryption php problem with keysize

The issue is why does a 32 character string work in C# .NET but not in php mcrypt, and how to make them compatible? (I have a method of doing it with AES, 3DES remains open.

I'm trying to create a cryptography api which uses Microsofts Crypto Api's in .NET and PHP's mcrypt to encrypt and decrypt data.

C# should be able to encrypt and decrypt, the PhP only needs to decrypt. The problem is I would like the user to be able to define their own key. To do this, I have md5 hashed the password they enter. This works perfectly on the C # side, but in PHP I get

Warning: mcrypt_decrypt() [function.mcrypt-decrypt]: Size of key is too large for this algorithm in C:\xampp\htdocs\failcrypt\crypt.php on line 40

(An empty "" string should work, as well as fairly large keys.

All the links I can find have preset keys, but mine must work for arbitrary key sizes on both sides.

        echo $key."</br>";
        echo md5($key)."</br>";
        $newKey = md5($key)."</br>";
        echo strlen($newKey)."</br>";
        $decrypted = mcrypt_decrypt(MCRYPT_3DES, md5($key), base64_decode($msg), MCRYPT_MODE_ECB);
        echo $decrypted;

outputs

red (the key)

bda9643ac6601722a28f238714274da4 (the hash)

Upvotes: 2

Views: 2671

Answers (1)

ixe013
ixe013

Reputation: 10171

The way you do it, the key size will never be arbitrary. It will always be the output of the MD5 hash. You are using a (weak) form of password based key derivation function (PBKDF). So the key really isn't the string "red", it is the output of the MD5 function.

 $ echo red | tr -d [:space:] | openssl dgst
 (stdin)= bda9643ac6601722a28f238714274da4

 $ echo The quick brown fox jumps over the lazy dog. | tr -d [:space:] | openssl dgst
 (stdin)= 09ecfef50e54940a3d241a10b7e70e3c

That being said, mcrypt_decrypt needs raw bytes for the key. Here is working code :

 $key = "Use any string you want as a password.";
 $encrypted = base64_decode("OcSlUzWMgac5RxYyt+An0g==");  //This is the base64 encoded cipher text

 $newKey = hash("md5", $key, TRUE); 
 //echo base64_encode($newKey)."\n";

 $decrypted = mcrypt_decrypt(MCRYPT_3DES, $newKey, $encrypted, MCRYPT_MODE_ECB);

 echo $decrypted;

You can increase the strength of your PBKDF by adding salt and iterating many times. So instead of using only :

md5(password)

Use something like

md5(salt+md5(salt+md5(salt+md5(salt+md5(salt+password)))))

You get the idea. Better yet, use a PBKDF2 implementation in C# and PHP that produce the same key.

Upvotes: 2

Related Questions