Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.1.0RC2

Bug #6159 Different results
Submitted: 2005-12-05 17:18 UTC
From: vichheann at yahoo dot fr Assigned: jausions
Status: Closed Package: Crypt_Blowfish
PHP Version: 5.0.3 OS: Fedora
Roadmaps: (Not assigned)    
Subscription  


 [2005-12-05 17:18 UTC] vichheann at yahoo dot fr
Description: ------------ The result of the encrypt function is not the same if i use Windows or Linux. I have XP SP2 and a Fedora Core 4. Test script: --------------- require_once "Crypt/Blowfish.php"; $plainText ="test"; $blowfish = new Crypt_Blowfish("mysecret"); $crypted = $blowfish->encrypt($plainText); // to have a human readable string $result = base64_encode($crypted); echo $result; echo "\n"; // to check that's base64_encode is ok $res = base64_encode($plainText); echo $res; Expected result: ---------------- Outputs should be same on both plateform Actual result: -------------- On Windows: A4iQeC9CuA4= dGVzdA== On Linux: j+bZjf/1YIA= dGVzdA==

Comments

 [2006-02-09 19:28 UTC] tautolog at gmail dot com
There seems to be a problem with the fact that PHP only supports signed ints, and all of these operations are for unsigned int. It seems that on 64 bit systems, bitwise logic works, but on 32 bit systems, the ints get truncated as the manual says when being casted for the operator. I am guessing the Linux didn't have mcrypt installed, and the Windows did, or that the Windows was 64 bit.
 [2006-02-09 20:29 UTC] vichheann at yahoo dot fr
It's interesting but i don't have 64bits machine. I made some tests using VirtualPC 2004. I tried Mandriva2006 and Ubuntu 5.10. The results are the same as my FC4 box, so still differents to my windows. I have access to a another machine running RH7.2 and compiled PHP5 and it worked!! Same results as windows. I made another test with another machine running FC1 and PHP4. It worked too. I asked a friend to test it on his MacOSX with PHP5 and it worked. Finally, I installed mcrypt on my FC4 box since Crypt_Blowfish uses it first. The tests have succedeed, so i decided to install mcrypt on the others linux and it was good. But it's not what I want. I need a encryption lib full PHP without using mcrypt. I can't figure out why it works on some linux and doesn't on others. Very strange.
 [2006-02-10 19:59 UTC] tautolog at gmail dot com
Odd. It worked for us on a 64 bit Windows box, and a 2.4 Linux box. Not on a 2.6 Linux box, and not on my DragonFlyBSD 1.4 box (FreeBSD 4 fork). An easy test is this something like this: -2861207174 ^ 493813264 Which is the operation that was different in our test. good: 1209765738 bad: -1653670384 -2861207174 is out of range of PHP_MIN_INT or LONG_MIN, which is -2147483648. The funny thing is that I can reproduce the "good" results by doing -(2861207174 ^ 493813264). Probably because it is being stored internally as unsigned or something, when it can. I also noticed that on the good box, (float) -2861207174 ^ 493813264 still produces the good results. It seems to me that some systems are doing float bitwise operations like integer bitwise operations, and others aren't.
 [2006-02-10 20:23 UTC] tautolog at gmail dot com
Zend is using this macro to convert floats to integers: #define DVAL_TO_LVAL(d, l) (l) = (d) > LONG_MAX ? (unsigned long) (d) : (long) (d) If it is longer than LONG_MAX, it stores it as an unsigned long, otherwise, it stores it as a signed long. Which seems to be why it works for me when I flip the sign before doing the operation, and then flip it back.
 [2006-03-10 18:01 UTC] klyuchka at gmail dot com (Alexander Klyuchka)
I have changed all "^" operators to use "binxor" function. Now it is working correctly with all systmes on which I tested it. function binxor($a, $b) { return bindec(decbin((float)$a ^ (float)$b)); } I have found this function in comments on PHP Manual: http://www.php.net/manual/en/language.operators.bitwise.php#56382 It was written by Eric Swanson.
 [2006-03-13 09:39 UTC] vichheann at yahoo dot fr
I've just tried what you said and it works! Thanks Alexander! I ran 'pear run-tests' on windows and fedora and all tests passed. This is a diff of what i've made: 128c128,137 < --- > > /** > * > * http://www.php.net/manual/en/language.operators.bitwise.php#56382 > */ > function binxor($a, $b) > { > return bindec(decbin((float)$a ^ (float)$b)); > } > 151,153c160,162 < $temp = $Xl ^ $this->_P[$i]; < $Xl = ((($this->_S[0][($temp>>24) & 255] + < $this->_S[1][($temp>>16) & 255]) ^ --- > $temp =$this-> binxor($Xl, $this->_P[$i]); > $Xl = $this->binxor($this->binxor($this->_S[0][($temp>>24) & 255] + > $this->_S[1][($temp>>16) & 255], 155c164 < $this->_S[3][$temp & 255]) ^ $Xr; --- > $this->_S[3][$temp & 255], $Xr); 158,159c167,168 < $Xr = $Xl ^ $this->_P[16]; < $Xl = $temp ^ $this->_P[17]; --- > $Xr = $this->binxor($Xl, $this->_P[16]); > $Xl = $this->binxor($temp, $this->_P[17]); 173,175c182,184 < $temp = $Xl ^ $this->_P[$i]; < $Xl = ((($this->_S[0][($temp>>24) & 255] + < $this->_S[1][($temp>>16) & 255]) ^ --- > $temp = $this->binxor($Xl, $this->_P[$i]); > $Xl = $this->binxor($this->binxor($this->_S[0][($temp>>24) & 255] + > $this->_S[1][($temp>>16) & 255], 177c186 < $this->_S[3][$temp & 255]) ^ $Xr; --- > $this->_S[3][$temp & 255], $Xr); 180,181c189,190 < $Xr = $Xl ^ $this->_P[1]; < $Xl = $temp ^ $this->_P[0]; --- > $Xr = $this->binxor($Xl, $this->_P[1]); > $Xl = $this->binxor($temp, $this->_P[0]); Matthew, would it be possible to fix it for a new release please?
 [2006-04-06 18:17 UTC] jausions (Philippe Jausions)
For performance reasons: this function should have a switch for 64-bit platforms only. function _binxor($a, $b) { return (PHP_INT_SIZE > 4) ? bindec(decbin((float)$a ^ (float)$b)) : ($a ^ $b); }
 [2006-04-06 19:49 UTC] jausions (Philippe Jausions)
Ok, I think this is not the whole picture. First the bindec/decbin is a huge performance killer. Second, it may have to do with the unpack("N2") and big unsigned 32-bit ending as signed integers. I don't have a access to a 64-bit machine, so I can't really do tests... Can any of you do some tests using: function _unpackN2($input) { list(, $Xl, $Xr) = unpack('N2', $input); return array( ($Xl < 0) ? ($Xl ^ 4294967296) : $Xl, ($Xr < 0) ? ($Xr ^ 4294967296) : $Xr); } and replacing the calls to unpack("N2"...) with $this->_unpackN2(...)?
 [2006-04-06 22:13 UTC] vichheann at yahoo dot fr
Hi, Philippe, I did what you said and run the tests on windows and linux but they failed: Notice: Undefined offset: 2 in D:\dev\tools\php-5.0.4\PEAR\Crypt\Blowfish.php on line 215 It's where i've replaced unpack by your _unpackN2 I don't have 64-bit machine so no tests.
 [2006-04-26 17:30 UTC] jausions (Philippe Jausions)
Thank you for taking the time to report a problem with the package. This problem may have been already fixed by a previous change that is in the CVS of the package. Please log into CVS with: cvs -d :pserver:cvsread@cvs.php.net:/repository login and check out the CVS repository of this package and upgrade cvs -d :pserver:cvsread@cvs.php.net:/repository co pear/Crypt_Blowfish pear upgrade pear/Crypt_Blowfish/package2.xml or pear upgrade pear/Crypt_Blowfish/package.xml If you are able to reproduce the bug with the latest CVS, please change the status back to "Open". Again, thank you for your continued support of PEAR. Ok, let's see if the CVS version works for you. I don't have access to a machine which would have the problem with this bug, so please bear with us while we're trying to find a reasonable solution to this. The binxor() proposed seems to work from your comment, but it is a major performance killer, 6 times as slow as ^ alone... Let me know, Thanks -Philippe
 [2006-04-27 19:15 UTC] vichheann at yahoo dot fr
I checked out the last sources on CVS and use them to update my local pear install. I launched then the tests with 'pear run-tests' but they failed on windows and linux. I also tried to use this new version with my code but it failed too. So I'm sorry to say that but it seems that the last commit has not been tested (it should work on windows at least). Or maybe I miss something? I trust you when you say the solution with binxor() is a performance killer. But in my case, it's not so important (well, for now ...).
 [2006-05-05 14:46 UTC] jausions (Philippe Jausions)
Thank you for taking the time to report a problem with the package. This problem may have been already fixed by a previous change that is in the CVS of the package. Please log into CVS with: cvs -d :pserver:cvsread@cvs.php.net:/repository login and check out the CVS repository of this package and upgrade cvs -d :pserver:cvsread@cvs.php.net:/repository co pear/Crypt_Blowfish pear upgrade pear/Crypt_Blowfish/package2.xml or pear upgrade pear/Crypt_Blowfish/package.xml If you are able to reproduce the bug with the latest CVS, please change the status back to "Open". Again, thank you for your continued support of PEAR. I've found a system with the same problem and the newest packing now in CVS seems to be working fine on it. The code is not cleaned up yet, I'm waiting on your input before removing some debug code and such. My latest fix is considerably faster than the bindec(decbin()) solution. I would also like to know if that fix works on a 64-bit system, as I'm adding floats to offset the PHP_INT_MAX limit.
 [2006-05-15 09:49 UTC] vichheann at yahoo dot fr
Good news, the latest sources from CVS work on my windows and my linux !! You've made a good job, thanks! I can't tell you about 64-bit machine because I don't have such a machine, sorry. I'm looking forward to the next release.
 [2006-06-16 09:09 UTC] ronyo at freemail dot hu (ronyo)
I don't know if this helps, but I used this trick to keep away the 4-byte int values to type cast upward to 8-byte ones: function intAdd($a, $b) { if (($a & 0x80000000) == ($b & 0x80000000)) { return (($a & 0x7fffffff) + ($b & 0x7fffffff)); } else { return (($a & 0x7fffffff) + ($b & 0x7fffffff)) + 0x80000000; } } And in _encipher and _decipher functions the $Xl is calculated like this: $Xl = $this->intAdd( ( $this->intAdd( $this->_S[0][($temp>>24) & 0x0ff], $this->_S[1][($temp>>16) & 0x0ff] ) ^ $this->_S[2][($temp>>8) & 0x0ff] ), $this->_S[3][$temp & 0x0ff] ) ^ $Xr;
 [2006-06-26 15:47 UTC] semipalakva at gmail dot com (Semipalakva)
I have similar problem. First mashine - 64 bits CPU - use Blowfish for encoding some "secret" information. Second machine - 32 bits CPU - use the same Blowfish for decoding "secret" information, but with bad result. Problem is with ^ operator. 64 bit CPU has longer integer type. What can I do? I have tried binxor but with no results.
 [2006-06-28 03:11 UTC] tautolog at gmail dot com
It seems to me the proper fix is to take advantage of the fact that PHP's bitwise operators work on strings, and use strings instead of inadequate integers. That would probably also be a much better performer than the other suggested fix.
 [2006-09-09 02:55 UTC] jausions (Philippe Jausions)
Thank you for your bug report. This issue has been fixed in the latest released version of the package, which you can download at http://pear.php.net/get/Crypt_Blowfish