diff --git a/phpseclib/Math/BigInteger/Engines/GMP.php b/phpseclib/Math/BigInteger/Engines/GMP.php index 262e55c2..8dbb85a2 100644 --- a/phpseclib/Math/BigInteger/Engines/GMP.php +++ b/phpseclib/Math/BigInteger/Engines/GMP.php @@ -517,7 +517,14 @@ class GMP extends Engine $result->bitmask = $this->bitmask; if ($result->bitmask !== false) { + $flip = $result->value < 0; + if ($flip) { + $result->value = -$result->value; + } $result->value = $result->value & $result->bitmask->value; + if ($flip) { + $result->value = -$result->value; + } } return $result; diff --git a/phpseclib/Math/BigInteger/Engines/PHP.php b/phpseclib/Math/BigInteger/Engines/PHP.php index a313b484..24226952 100644 --- a/phpseclib/Math/BigInteger/Engines/PHP.php +++ b/phpseclib/Math/BigInteger/Engines/PHP.php @@ -157,6 +157,7 @@ abstract class PHP extends Engine } $temp = clone $this; + $temp->bitmask = false; $temp->is_negative = false; $divisor = new static(); diff --git a/tests/Unit/Math/BigInteger/TestCase.php b/tests/Unit/Math/BigInteger/TestCase.php index 56d2234d..c8445238 100644 --- a/tests/Unit/Math/BigInteger/TestCase.php +++ b/tests/Unit/Math/BigInteger/TestCase.php @@ -485,4 +485,21 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase $temp = $this->getInstance('-0'); $this->assertSame($temp->toString(), '0'); } + + public function testNegativePrecision() + { + $vals = [ + '-9223372036854775808', // eg. 8000 0000 0000 0000 + '-1' + ]; + foreach ($vals as $val) { + $x = $this->getInstance($val); + $x->setPrecision(64); // ie. 8 bytes + $this->assertSame($val, "$x"); + $r = $x->toBytes(true); + $this->assertSame(8, strlen($r)); + $x2 = $this->getInstance($r, -256); + $this->assertSame(0, $x->compare($x2)); + } + } }