I came across an issue a few years back that I was supposed to post about there and then; what the hey no buggers bothered to fix it.
Basically PHP – MCrypt is great, it handles lots of nice encryption algorithms very simply and provides just the right amount of abstraction to the user to make it usable.
What it doesn’t do is handle all of the regularly used encryption standards used by say Java (think Apache Tomcat) or .Net (IIS/Mono); one of the main one of these being TripleDES (ECB with PKCS5 Padding). It WILL handle TripleDES on its own, the important bit is the ECB-PKCS5 Padding, as without this a message size and form is different and subsequently any attempt to decrypt that message will return junk.
I wont go into boring detail about the encryption as I expect most of you who came here came just for the code and have copied-pasted and left
So here’s the code…
<?php function encrypt($input,$ky) { $key = $ky; $size = mcrypt_get_block_size(MCRYPT_TRIPLEDES, 'ecb'); $input = pkcs5_pad($input, $size); $td = mcrypt_module_open(MCRYPT_TRIPLEDES, '', 'ecb', ''); $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); mcrypt_generic_init($td, $key, $iv); $data = mcrypt_generic($td, $input); mcrypt_generic_deinit($td); mcrypt_module_close($td); $data = base64_encode($data); $data = urlencode($data); //push it out so i can check it works return $data; } function decrypt($crypt,$ky) { $crypt = urldecode($crypt); $crypt = base64_decode($crypt); $key = $ky; $td = mcrypt_module_open (MCRYPT_TRIPLEDES, '', 'ecb', ''); $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); mcrypt_generic_init($td, $key, $iv); $decrypted_data = mdecrypt_generic ($td, $crypt); mcrypt_generic_deinit ($td); mcrypt_module_close ($td); $decrypted_data = pkcs5_unpad($decrypted_data); $decrypted_data = rtrim($decrypted_data); return $decrypted_data; } function pkcs5_pad($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); } function pkcs5_unpad($text) { $pad = ord($text{strlen($text)-1}); if ($pad > strlen($text)) return false; return substr($text, 0, -1 * $pad); } //Quick Test $key = 'ZEjygIuripyRcusWBBlyWZz='; $x = "Sometimes a little encryption is better than none"; echo "<b>String:</b> $x <br><br>"; echo"<b>Encrypted:</b><br><br>"; $testd = encrypt($x, $key); echo $testd; echo"<br><br><br><b>Decrypt</b><br>"; $d = decrypt($testd,$key); echo $d; ?> |
To make myself happy here’s a pretty picture of Electronic codebook (ECB)

source http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
And here’s a little bit on this encryption. Basically put the block cipher requires input that is an exact multiple of the block size; so If the input buffer is not a multiple of the block size, it must be padded to fill up the last block, here’s where padding comes into play. This form of encryptions not bad, I probably wouldn’t feel comfortable keeping my bank details in it but it was good enough for the nice people at a very large crisp company to use as to authenticate all its discounts in a large British campaign.
There’s a fair bit on this and the padding:
- http://www.di-mgt.com.au/cryptopad.html#whennopadding
- http://www.ietf.org/rfc/rfc3369.txt
- http://www.haskell.org/crypto/doc/html/Codec-Encryption-Padding.html#v%3Apkcs5
Yes, I have to use PKCS5Padding too. The first 8 chars are something like this 'D ���.53'. Thanks for the reply.
Yes, I need PKCS5Padding too
How about CBC mode ? I tried this for CBC mode (I replaced 'ecb' with 'cbc' for mcrypt mode) but it does not work. The first part of decrypted string (first 8 chars) is wrong. Do you have any ideas ? Thanks.
Are you using PKCS5Padding with that?
If not you can just use ... http://php.net/manual/en/function.mcrypt-cbc.php
Great!
Thanks for publishing this. That's exactly what I was looking for!
Your pkcs5_pad() function did it. Fantastic job.
Cheers
Renato
No probs, glad you worked it out. I was using a fedora based system with php 5.0 when this was written, but have since tested it on a debian and freebsd system running 5.3.
Thanks, BTW! Great post!
Nevermind, it works just not in the Grails PHP plugin...
This example doesn't work for me. It doesn't show anything in the test portion that echo's out the decrypt results
You are using Php5 right?