2

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)

7
  • Looks like something happens with the key while you transport it. I would smell an encoding issue, however you wrote it's a MD5 hash which should not have obvious encoding issues when transported. How do you pass the key string from c# to PHP? Commented Jul 6, 2011 at 18:48
  • @hakre The key can be hardcoded right now, its just that both the php and c# must be able to use the same key Commented Jul 6, 2011 at 19:00
  • 1
    Hmm, the strlen you give in your question is wrong. I get 32 for the has, not 37. ? Commented Jul 6, 2011 at 19:01
  • 1
    The strlen you're echoing includes the <br /> characters... Commented Jul 6, 2011 at 19:03
  • Yea, I didn't notice the </br>, but the question is really how to use the same string (key) on both sides. Commented Jul 6, 2011 at 19:25

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but do you know how I would get both the C# and PHP to work with arbitrary key sizes?
+1 for PBKDF. See PKCS#5 for details.
@ixe013 Yea, I get that I'm using the hash, the problem is that the php 3des doesn't want to take the hashed key as input, it says the key is too large.
The key must be raw bytes. I added working code to my answer.

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.