Introduction
I recently worked on a project that required encryption and decryption by and between .NET and PHP. By default, the 2 technologies don’t mesh very well. Being that the data was originally being encrypted and decrypted by .NET, I had to write PHP code that worked with the encryption schemas being used. One of the main problems I ran into was the use of padding, in my case pkcs7
which was used by default in .NET.
Getting Started
First thing to do was to make sure the encyption schemas were the same. For example, when using DES
, the .NET default mode is MCRYPT_MODE_CBC
. Once that was setup, I could initialize the mcrypt libraries.
$module = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, '');
if($module === false)
die("DES module could not be opened");
$blockSize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
The $blockSize
variable is used later for padding and padding removal using pkcs7
.
Encryption
Next to encrypt data I had to implement the following:
//encryption
$key = substr($key, 0, 8);
$iv = $key;
$rc = mcrypt_generic_init($module, $key, $iv);
//apply pkcs7 padding
$value_length = strlen($value);
$padding = $blockSize - ($value_length % $blockSize);
$value .= str_repeat( chr($padding), $padding);
$value = mcrypt_generic($module, $value);
$value = base64_encode($value);
mcrypt_generic_deinit($module);
//value now encrypted
Basically, the encryption scheme the .NET side was using was set the iv to the key, pad data, encrypt data, then base64 encode data. So here I’ve done the same thing in PHP.
Decryption
Now I needed to do the exact same thing for decryption:
//Decryption
$key = substr($key, 0, 8);
$iv = $key;
$rc = mcrypt_generic_init($module, $key, $iv);
$value = base64_decode($value);
$value = mdecrypt_generic($module, $value);
//apply pkcs7 padding removal
$packing = ord($value[strlen($value) - 1]);
if($packing && $packing < $this->_blockSize){
for($P = strlen($value) - 1; $P >= strlen($value) - $packing; $P--){
if(ord($value{$P}) != $packing){
$packing = 0;
}//end if
}//end for
}//end if
$value = substr($value, 0, strlen($value) - $packing);
mcrypt_generic_deinit($module);
//value now decrypted
This is basically the same as encryption but in reverse. The only real difference is the pkcs7
padding removal.
Conclusion
Hopefully this tidbit helps a few others out there who run into encrypt and decryption issues between .NET and PHP.
8 Comments
Faba · May 23, 2011 at 9:14 am
Hi! I’m using Silverlight to encrypt text (using AesManaged class) and then write it to file (using CryptoStream). After this in PHP i read file (‘rb’ mode) and using your script tried to decrypt it. There is an error in ‘$value = mdecrypt_generic($module, $value);’ line. After ‘$value = base64_decode($value);’ line $value is empty.. Do you know the solution to this problem?
Thanks.
GodLikeMouse · May 23, 2011 at 5:46 pm
Have you verified that your mcrypt libraries are installed and working? If not, I would write a simple encrypt print, decrypt print, PHP script run it on a simple text value and make sure it works as expected. Next check your input values before and after the decrypt call to make sure they contain what you think they should and that there are no extra characters being passed down the line (ie. n, r, etc). Let me know if that works or not.
Faba · May 25, 2011 at 7:03 am
mcrypt libraries are install. I tried simple text value and encrypt-decrypt it with your code – it works. But when I encrypt this string in Silverlight – decrypt code (in PHP) doesn’t work. This simple text value after encrypt is different between Silverlight and PHP methods.
GodLikeMouse · May 25, 2011 at 5:31 pm
Hmmm…let’s try this. Take a simple value like “hello”, encode it using Silverlight, then encode it using normal .NET. Compare the 2 results and see what’s different. It’s possible that Silverlight is not padding or that it’s doing something else unexpected. If you could, please post both encoded strings here so I can have a look at them.
Juventus · August 10, 2012 at 5:39 pm
You are the man! I’ve been working on encryption/decryption between C#/PHP for 3 days now, so close – kept getting partial strings decrypted. I applied your padding fix (on the php decryption side) BINGO! works like a charm! You’re the man!
GodLikeMouse · August 10, 2012 at 9:04 pm
Sweet, glad it helped 🙂
Leonardo Mauro · November 27, 2015 at 9:56 am
Great,
I work with PHP only four years.. and just need crypt now.
I had some dificult with decrypt, guilt of padding (pkcs7).
Your algorithm help me alot .. Thankss!
godlikemouse · November 27, 2015 at 2:28 pm
Glad to have helped.