...

View Full Version : php + c# + DES3 + PKCS Padding = nightmare guru's needed



hinch
05-24-2011, 12:29 PM
ok so I'm having a rather odd issue with some php to c# based encrypting as in it sometimes works 100% and sometimes works randomly ie: works for some variables not for others
Now today i'm having one of the part working days (tomorrow it'll probably work perfectly :( )

Basically I'm encrypting a load of variables with a pre-set key and sending them to a remote server thats running a c# platform. I think the problem lies in a combination of day + blocksize creation for padding but I can't pin it down and was just wondering if a fresh set of eyes may resolve it for me.

Here's the encrypt + padding code including our key generation system as the key is a combination of a static key string + day effectors


function pkcs7_pad($text, $blocksize) {
// padding function required to make php match C#
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}

function desencrypt($input) {
// SSOKey as supplied
$ssokey = 'g4h5cjdf57hjjdpjo41xd6awe7qwxvxz';
//calc date offset
$todaysdate = date("z")+1;
//update key with todays date
if (strlen($todaysdate)>0) {
$newkey = $todaysdate.substr($ssokey,strlen($todaysdate),strlen($ssokey));
}
//decode key to binary
$key = base64_decode($newkey);
/* Open mcrypt module */
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$blockSize = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
//pad out input to match C# defaults
$input = pkcs7_pad($input, $blockSize);
//$input = pkcs7_pad($input, 8);
/* Intialize encryption */
mcrypt_generic_init($td, $key, $iv);
/* Encrypt data */
$encrypted = mcrypt_generic($td, $input);
/* Terminate encryption handler */
mcrypt_generic_deinit($td);
/* close module */
mcrypt_module_close($td);
/* return encrypted string */
return base64_encode(trim($encrypted));

}

now if I encrypt the value 6 using htmlentities(desencrypt("6"))
I get kaKbuHmi1JU= in both PHP and C# which is perfect.
However if I encrypt a value of 1 I get Cd7JeO2YckI= for C# and 3sl47ZhyQg== for PHP which is obviously wrong.

All other strings being encoded today are working just fine its just the issue with the number 1 being encrypted and as said it sometimes works perfectly other times it doesn't like today.

Can anyone see anything obviously wrong with my code or padding. Or have you got some suggestions of stuff I can test/attempt.

Any help will be much appreciated with many thanks

Inigoesdr
05-25-2011, 12:54 AM
However if I encrypt a value of 1 I get Cd7JeO2YckI= for C# and 3sl47ZhyQg== for PHP which is obviously wrong.

The result from C# has a tab at the beginning, and your PHP version doesn't. That is probably being stripped by this:

return base64_encode(trim($encrypted));
You should either remove the trim() (http://php.net/trim) or trim it in C#.

hinch
05-26-2011, 11:12 AM
ok i can trim it in the C# but that then raises the question why it works sometimes and other times doesn't.

its strange because the trim() in the php was put in because php was adding in an extra space at the end of the pre-encrypted string which was initially causing wrong strings this resolved the first part of of the problem :)

I'll add in a trim on the c# side of things and see if that helps

hinch
05-26-2011, 11:17 AM
here's an interesting one today its encrypting the variable with value 1 fine today

its now failing on a variable with value 2641 php creates I5hRDOJTWA== and c# creates ICOYUQziU1g=

Riceburner
05-26-2011, 11:44 AM
Hinch - could you comment on getting .NET encrypted strings decrypted in PHP?

I am trying to decrypt a cookie string that was encrypted in .NET, using TripleDES. The Key is a 16Character ASCII string, that has allegedly been encoded into HEX. What confuses me is that this creates a 32Character string (256bits), but everything I've read says that TripleDES can only accept a 198bit (24characters) string. :confused:

PHP's mcrypt_decrypt certainly only uses the first 24 characters in a supplied string.

hinch
05-26-2011, 11:54 AM
yeah there is a difference in key length between the 2 thats where the padding comes into play.

For decryption you'll have to strip the padding after decryption (it should be padded with zero's) I've not actually written the decryption function for php because i need to go from encrypt in php to decrypt in c# other way around to you.

If I get chance I'll look into knocking together a php decrypt function for you just abit busy this week

Riceburner
05-26-2011, 11:57 AM
yeah there is a difference in key length between the 2 thats where the padding comes into play.

For decryption you'll have to strip the padding after decryption (it should be padded with zero's) I've not actually written the decryption function for php because i need to go from encrypt in php to decrypt in c# other way around to you.

If I get chance I'll look into knocking together a php decrypt function for you just abit busy this week

I appreciate that the string to be encrypted will be padded - but what about the key-length issue??

Or does the Key I'm using have to be padded?? How would that work when the key is too long for php?? Or do I pad it before Hex-ing it?? I've tried that and it just creates an even longer Hex string which fires the same error/warning in php. :confused:

hinch
05-26-2011, 03:45 PM
i believe that if you have say a 32 char key and php only accepts 24 then it takes the first 24 chars of the key.

though don't hold me to that.

Inigoesdr
05-26-2011, 03:46 PM
here's an interesting one today its encrypting the variable with value 1 fine today

its now failing on a variable with value 2641 php creates I5hRDOJTWA== and c# creates ICOYUQziU1g=
The C# version has a space at the beginning which is causing the difference.

Riceburner
05-26-2011, 05:14 PM
i believe that if you have say a 32 char key and php only accepts 24 then it takes the first 24 chars of the key.

though don't hold me to that.

Yes, that's what happens. (and php also throws a warning).

But if the .NET encryption process DOES (for some reason) accept a 32 character key, then it would appear that PHP can't decrypt the string properly? I have trouble believing that this would be the case.

hinch
05-27-2011, 12:29 PM
The C# version has a space at the beginning which is causing the difference.

yeah i figured the additional = at the end was meaning an additional space i've removed the trim() from my encrypt now which appears to have fixed it however I won't know for sure until dates trip over back to single digit days as I suspect on single digit days we overpad as opposed to underpad (as now) and so the trim will have to return.

if thats the case I'll just have to put a detect in there for day length and take it from there

hinch
05-27-2011, 12:30 PM
Yes, that's what happens. (and php also throws a warning).

But if the .NET encryption process DOES (for some reason) accept a 32 character key, then it would appear that PHP can't decrypt the string properly? I have trouble believing that this would be the case.

I believe this issue is well documented around the net and is indeed the case I'm not entirely sure how it'd be resolved though and I haven't really had chance to look into it unfortunately still attempting to solve my own issue at the moment :(

Riceburner
05-27-2011, 03:20 PM
yeah i figured the additional = at the end was meaning an additional space i've removed the trim() from my encrypt now which appears to have fixed it however I won't know for sure until dates trip over back to single digit days as I suspect on single digit days we overpad as opposed to underpad (as now) and so the trim will have to return.

if thats the case I'll just have to put a detect in there for day length and take it from there

Could you use double digit days? (01,02 etc)??

I'm waiting to see what the .NET devs have done in their encryption process to possibly solve my issue.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum