first commit
This commit is contained in:
620
pgserver/vendor/mdanter/ecc/src/Math/DebugDecorator.php
vendored
Normal file
620
pgserver/vendor/mdanter/ecc/src/Math/DebugDecorator.php
vendored
Normal file
@@ -0,0 +1,620 @@
|
||||
<?php
|
||||
|
||||
namespace Mdanter\Ecc\Math;
|
||||
|
||||
use Mdanter\Ecc\Primitives\GeneratorPoint;
|
||||
|
||||
/**
|
||||
* Debug helper class to trace all calls to math functions along with the provided params and result.
|
||||
*/
|
||||
class DebugDecorator implements GmpMathInterface
|
||||
{
|
||||
/**
|
||||
* @var GmpMathInterface
|
||||
*/
|
||||
private $adapter;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $writer;
|
||||
|
||||
/**
|
||||
* @param GmpMathInterface $adapter
|
||||
* @param callable|null $callback
|
||||
*/
|
||||
public function __construct(GmpMathInterface $adapter, callable $callback = null)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
$this->writer = $callback ?: function ($message) {
|
||||
echo $message;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
private function write($message)
|
||||
{
|
||||
call_user_func($this->writer, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $func
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
*/
|
||||
private function call($func, $args)
|
||||
{
|
||||
$strArgs = array_map(
|
||||
function ($arg) {
|
||||
if ($arg instanceof \GMP) {
|
||||
return var_export($this->adapter->toString($arg), true);
|
||||
} else {
|
||||
return var_export($arg, true);
|
||||
}
|
||||
},
|
||||
$args
|
||||
);
|
||||
|
||||
if (strpos($func, '::')) {
|
||||
list(, $func) = explode('::', $func);
|
||||
}
|
||||
|
||||
$this->write($func.'('.implode(', ', $strArgs).')');
|
||||
|
||||
$res = call_user_func_array([ $this->adapter, $func ], $args);
|
||||
|
||||
if ($res instanceof \GMP) {
|
||||
$this->write(' => ' . var_export($this->adapter->toString($res), true) . PHP_EOL);
|
||||
} else {
|
||||
$this->write(' => ' . var_export($res, true) . PHP_EOL);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::cmp()
|
||||
*/
|
||||
public function cmp(\GMP $first, \GMP $other): int
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::cmp()
|
||||
*/
|
||||
public function equals(\GMP $first, \GMP $other): bool
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::mod()
|
||||
*/
|
||||
public function mod(\GMP $number, \GMP $modulus): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::add()
|
||||
*/
|
||||
public function add(\GMP $augend, \GMP $addend): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::sub()
|
||||
*/
|
||||
public function sub(\GMP $minuend, \GMP $subtrahend): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::mul()
|
||||
*/
|
||||
public function mul(\GMP $multiplier, \GMP $multiplicand): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::div()
|
||||
*/
|
||||
public function div(\GMP $dividend, \GMP $divisor): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::pow()
|
||||
*/
|
||||
public function pow(\GMP $base, int $exponent): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::bitwiseAnd()
|
||||
*/
|
||||
public function bitwiseAnd(\GMP $first, \GMP $other): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\MathAdapter::toString()
|
||||
*/
|
||||
public function toString(\GMP $value): string
|
||||
{
|
||||
return $this->adapter->toString($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::hexDec()
|
||||
*/
|
||||
public function hexDec(string $hexString): string
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::decHex()
|
||||
*/
|
||||
public function decHex(string $decString): string
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::powmod()
|
||||
*/
|
||||
public function powmod(\GMP $base, \GMP $exponent, \GMP $modulus): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::isPrime()
|
||||
*/
|
||||
public function isPrime(\GMP $n): bool
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::nextPrime()
|
||||
*/
|
||||
public function nextPrime(\GMP $currentPrime): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::inverseMod()
|
||||
*/
|
||||
public function inverseMod(\GMP $a, \GMP $m): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::jacobi()
|
||||
*/
|
||||
public function jacobi(\GMP $a, \GMP $p): int
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::intToString()
|
||||
*/
|
||||
public function intToFixedSizeString(\GMP $x, int $byteSize): string
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::intToString()
|
||||
*/
|
||||
public function intToString(\GMP $x): string
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::stringToInt()
|
||||
*/
|
||||
public function stringToInt(string $s): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::digestInteger()
|
||||
*/
|
||||
public function digestInteger(\GMP $m): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::gcd2()
|
||||
*/
|
||||
public function gcd2(\GMP $a, \GMP $m): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::rightShift()
|
||||
*/
|
||||
public function rightShift(\GMP $number, int $positions): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::leftShift()
|
||||
*/
|
||||
public function leftShift(\GMP $number, int $positions): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call',
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::bitwiseXor()
|
||||
*/
|
||||
public function bitwiseXor(\GMP $first, \GMP $other): \GMP
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call'
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::baseConvert()
|
||||
*/
|
||||
public function baseConvert(string $value, int $fromBase, int $toBase): string
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call'
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::getEcMath()
|
||||
*/
|
||||
public function getEcMath(GeneratorPoint $generatorPoint, $input)
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call'
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::getModularArithmetic()
|
||||
*/
|
||||
public function getModularArithmetic(\GMP $modulus): ModularArithmetic
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call'
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Mdanter\Ecc\Math\GmpMathInterface::getNumberTheory()
|
||||
*/
|
||||
public function getNumberTheory(): NumberTheory
|
||||
{
|
||||
$func = __METHOD__;
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func(
|
||||
array(
|
||||
$this,
|
||||
'call'
|
||||
),
|
||||
$func,
|
||||
$args
|
||||
);
|
||||
}
|
||||
}
|
||||
333
pgserver/vendor/mdanter/ecc/src/Math/GmpMath.php
vendored
Normal file
333
pgserver/vendor/mdanter/ecc/src/Math/GmpMath.php
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
namespace Mdanter\Ecc\Math;
|
||||
|
||||
use Mdanter\Ecc\Util\BinaryString;
|
||||
use Mdanter\Ecc\Util\NumberSize;
|
||||
|
||||
class GmpMath implements GmpMathInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::cmp()
|
||||
*/
|
||||
public function cmp(\GMP $first, \GMP $other): int
|
||||
{
|
||||
return gmp_cmp($first, $other);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $first
|
||||
* @param \GMP $other
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(\GMP $first, \GMP $other): bool
|
||||
{
|
||||
return gmp_cmp($first, $other) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::mod()
|
||||
*/
|
||||
public function mod(\GMP $number, \GMP $modulus): \GMP
|
||||
{
|
||||
return gmp_mod($number, $modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::add()
|
||||
*/
|
||||
public function add(\GMP $augend, \GMP $addend): \GMP
|
||||
{
|
||||
return gmp_add($augend, $addend);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::sub()
|
||||
*/
|
||||
public function sub(\GMP $minuend, \GMP $subtrahend): \GMP
|
||||
{
|
||||
return gmp_sub($minuend, $subtrahend);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::mul()
|
||||
*/
|
||||
public function mul(\GMP $multiplier, \GMP $multiplicand): \GMP
|
||||
{
|
||||
return gmp_mul($multiplier, $multiplicand);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::div()
|
||||
*/
|
||||
public function div(\GMP $dividend, \GMP $divisor): \GMP
|
||||
{
|
||||
return gmp_div($dividend, $divisor);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::pow()
|
||||
*/
|
||||
public function pow(\GMP $base, int $exponent): \GMP
|
||||
{
|
||||
return gmp_pow($base, $exponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::bitwiseAnd()
|
||||
*/
|
||||
public function bitwiseAnd(\GMP $first, \GMP $other): \GMP
|
||||
{
|
||||
return gmp_and($first, $other);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::rightShift()
|
||||
*/
|
||||
public function rightShift(\GMP $number, int $positions): \GMP
|
||||
{
|
||||
// Shift 1 right = div / 2
|
||||
return gmp_div($number, gmp_pow(gmp_init(2, 10), $positions));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::bitwiseXor()
|
||||
*/
|
||||
public function bitwiseXor(\GMP $first, \GMP $other): \GMP
|
||||
{
|
||||
return gmp_xor($first, $other);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::leftShift()
|
||||
*/
|
||||
public function leftShift(\GMP $number, int $positions): \GMP
|
||||
{
|
||||
// Shift 1 left = mul by 2
|
||||
return gmp_mul($number, gmp_pow(2, $positions));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::toString()
|
||||
*/
|
||||
public function toString(\GMP $value): string
|
||||
{
|
||||
return gmp_strval($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::hexDec()
|
||||
*/
|
||||
public function hexDec(string $hex): string
|
||||
{
|
||||
return gmp_strval(gmp_init($hex, 16), 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::decHex()
|
||||
*/
|
||||
public function decHex(string $dec): string
|
||||
{
|
||||
$dec = gmp_init($dec, 10);
|
||||
|
||||
if (gmp_cmp($dec, 0) < 0) {
|
||||
throw new \InvalidArgumentException('Unable to convert negative integer to string');
|
||||
}
|
||||
|
||||
$hex = gmp_strval($dec, 16);
|
||||
|
||||
if (BinaryString::length($hex) % 2 != 0) {
|
||||
$hex = '0'.$hex;
|
||||
}
|
||||
|
||||
return $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::powmod()
|
||||
*/
|
||||
public function powmod(\GMP $base, \GMP $exponent, \GMP $modulus): \GMP
|
||||
{
|
||||
if ($this->cmp($exponent, gmp_init(0, 10)) < 0) {
|
||||
throw new \InvalidArgumentException("Negative exponents (" . $this->toString($exponent) . ") not allowed.");
|
||||
}
|
||||
|
||||
return gmp_powm($base, $exponent, $modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::isPrime()
|
||||
*/
|
||||
public function isPrime(\GMP $n): bool
|
||||
{
|
||||
$prob = gmp_prob_prime($n);
|
||||
|
||||
if ($prob > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::nextPrime()
|
||||
*/
|
||||
public function nextPrime(\GMP $starting_value): \GMP
|
||||
{
|
||||
return gmp_nextprime($starting_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::inverseMod()
|
||||
*/
|
||||
public function inverseMod(\GMP $a, \GMP $m): \GMP
|
||||
{
|
||||
return gmp_invert($a, $m);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::jacobi()
|
||||
*/
|
||||
public function jacobi(\GMP $a, \GMP $n): int
|
||||
{
|
||||
return gmp_jacobi($a, $n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $x
|
||||
* @param int $byteSize
|
||||
* @return string
|
||||
*/
|
||||
public function intToFixedSizeString(\GMP $x, int $byteSize): string
|
||||
{
|
||||
if ($byteSize < 0) {
|
||||
throw new \RuntimeException("Byte size cannot be negative");
|
||||
}
|
||||
|
||||
if (gmp_cmp($x, 0) < 0) {
|
||||
throw new \RuntimeException("x was negative - not yet supported");
|
||||
}
|
||||
|
||||
$two = gmp_init(2);
|
||||
$range = gmp_pow($two, $byteSize * 8);
|
||||
if (NumberSize::bnNumBits($this, $x) >= NumberSize::bnNumBits($this, $range)) {
|
||||
throw new \RuntimeException("Number overflows byte size");
|
||||
}
|
||||
|
||||
$maskShift = gmp_pow($two, 8);
|
||||
$mask = gmp_mul(gmp_init(255), $range);
|
||||
|
||||
$binary = '';
|
||||
for ($i = $byteSize - 1; $i >= 0; $i--) {
|
||||
$mask = gmp_div($mask, $maskShift);
|
||||
$binary .= pack('C', gmp_strval(gmp_div(gmp_and($x, $mask), gmp_pow($two, $i * 8)), 10));
|
||||
}
|
||||
|
||||
return $binary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::intToString()
|
||||
*/
|
||||
public function intToString(\GMP $x): string
|
||||
{
|
||||
if (gmp_cmp($x, 0) < 0) {
|
||||
throw new \InvalidArgumentException('Unable to convert negative integer to string');
|
||||
}
|
||||
|
||||
$hex = gmp_strval($x, 16);
|
||||
|
||||
if (BinaryString::length($hex) % 2 != 0) {
|
||||
$hex = '0'.$hex;
|
||||
}
|
||||
|
||||
return pack('H*', $hex);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::stringToInt()
|
||||
*/
|
||||
public function stringToInt(string $s): \GMP
|
||||
{
|
||||
$result = gmp_init(0, 10);
|
||||
$sLen = BinaryString::length($s);
|
||||
|
||||
for ($c = 0; $c < $sLen; $c ++) {
|
||||
$result = gmp_add(gmp_mul(256, $result), gmp_init(ord($s[$c]), 10));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::digestInteger()
|
||||
*/
|
||||
public function digestInteger(\GMP $m): \GMP
|
||||
{
|
||||
return $this->stringToInt(hash('sha1', $this->intToString($m), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::gcd2()
|
||||
*/
|
||||
public function gcd2(\GMP $a, \GMP $b): \GMP
|
||||
{
|
||||
while ($this->cmp($a, gmp_init(0)) > 0) {
|
||||
$temp = $a;
|
||||
$a = $this->mod($b, $a);
|
||||
$b = $temp;
|
||||
}
|
||||
|
||||
return $b;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::baseConvert()
|
||||
*/
|
||||
public function baseConvert(string $number, int $from, int $to): string
|
||||
{
|
||||
return gmp_strval(gmp_init($number, $from), $to);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see GmpMathInterface::getNumberTheory()
|
||||
*/
|
||||
public function getNumberTheory(): NumberTheory
|
||||
{
|
||||
return new NumberTheory($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $modulus
|
||||
* @return ModularArithmetic
|
||||
*/
|
||||
public function getModularArithmetic(\GMP $modulus): ModularArithmetic
|
||||
{
|
||||
return new ModularArithmetic($this, $modulus);
|
||||
}
|
||||
}
|
||||
227
pgserver/vendor/mdanter/ecc/src/Math/GmpMathInterface.php
vendored
Normal file
227
pgserver/vendor/mdanter/ecc/src/Math/GmpMathInterface.php
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace Mdanter\Ecc\Math;
|
||||
|
||||
interface GmpMathInterface
|
||||
{
|
||||
/**
|
||||
* Compares two numbers
|
||||
*
|
||||
* @param \GMP $first
|
||||
* @param \GMP $other
|
||||
* @return int less than 0 if first is less than second, 0 if equal, greater than 0 if greater than.
|
||||
*/
|
||||
public function cmp(\GMP $first, \GMP $other): int;
|
||||
|
||||
/**
|
||||
* @param \GMP $first
|
||||
* @param \GMP $other
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(\GMP $first, \GMP $other): bool;
|
||||
|
||||
/**
|
||||
* Returns the remainder of a division
|
||||
*
|
||||
* @param \GMP $number
|
||||
* @param \GMP $modulus
|
||||
* @return \GMP
|
||||
*/
|
||||
public function mod(\GMP $number, \GMP $modulus): \GMP;
|
||||
|
||||
/**
|
||||
* Adds two numbers
|
||||
*
|
||||
* @param \GMP $augend
|
||||
* @param \GMP $addend
|
||||
* @return \GMP
|
||||
*/
|
||||
public function add(\GMP $augend, \GMP $addend): \GMP;
|
||||
|
||||
/**
|
||||
* Substract one number from another
|
||||
*
|
||||
* @param \GMP $minuend
|
||||
* @param \GMP $subtrahend
|
||||
* @return \GMP
|
||||
*/
|
||||
public function sub(\GMP $minuend, \GMP $subtrahend): \GMP;
|
||||
|
||||
/**
|
||||
* Multiplies a number by another.
|
||||
*
|
||||
* @param \GMP $multiplier
|
||||
* @param \GMP $multiplicand
|
||||
* @return \GMP
|
||||
*/
|
||||
public function mul(\GMP $multiplier, \GMP $multiplicand): \GMP;
|
||||
|
||||
/**
|
||||
* Divides a number by another.
|
||||
*
|
||||
* @param \GMP $dividend
|
||||
* @param \GMP $divisor
|
||||
* @return \GMP
|
||||
*/
|
||||
public function div(\GMP $dividend, \GMP $divisor): \GMP;
|
||||
|
||||
/**
|
||||
* Raises a number to a power.
|
||||
*
|
||||
* @param \GMP $base The number to raise.
|
||||
* @param int $exponent The power to raise the number to.
|
||||
* @return \GMP
|
||||
*/
|
||||
public function pow(\GMP $base, int $exponent): \GMP;
|
||||
|
||||
/**
|
||||
* Performs a logical AND between two values.
|
||||
*
|
||||
* @param \GMP $first
|
||||
* @param \GMP $other
|
||||
* @return \GMP
|
||||
*/
|
||||
public function bitwiseAnd(\GMP $first, \GMP $other): \GMP;
|
||||
|
||||
/**
|
||||
* Performs a logical XOR between two values.
|
||||
*
|
||||
* @param \GMP $first
|
||||
* @param \GMP $other
|
||||
* @return \GMP
|
||||
*/
|
||||
public function bitwiseXor(\GMP $first, \GMP $other): \GMP;
|
||||
|
||||
/**
|
||||
* Shifts bits to the right
|
||||
* @param \GMP $number Number to shift
|
||||
* @param int $positions Number of positions to shift
|
||||
* @return \GMP
|
||||
*/
|
||||
public function rightShift(\GMP $number, int $positions): \GMP;
|
||||
|
||||
/**
|
||||
* Shifts bits to the left
|
||||
* @param \GMP $number Number to shift
|
||||
* @param int $positions Number of positions to shift
|
||||
* @return \GMP
|
||||
*/
|
||||
public function leftShift(\GMP $number, int $positions): \GMP;
|
||||
|
||||
/**
|
||||
* Returns the string representation of a returned value.
|
||||
*
|
||||
* @param \GMP $value
|
||||
* @return string
|
||||
*/
|
||||
public function toString(\GMP $value): string;
|
||||
|
||||
/**
|
||||
* Converts an hexadecimal string to decimal.
|
||||
*
|
||||
* @param string $hexString
|
||||
* @return int|string
|
||||
*/
|
||||
public function hexDec(string $hexString): string;
|
||||
|
||||
/**
|
||||
* Converts a decimal string to hexadecimal.
|
||||
*
|
||||
* @param int|string $decString
|
||||
* @return string
|
||||
*/
|
||||
public function decHex(string $decString): string;
|
||||
|
||||
/**
|
||||
* Calculates the modular exponent of a number.
|
||||
*
|
||||
* @param \GMP $base
|
||||
* @param \GMP $exponent
|
||||
* @param \GMP $modulus
|
||||
* @return \GMP
|
||||
*/
|
||||
public function powmod(\GMP $base, \GMP $exponent, \GMP $modulus): \GMP;
|
||||
|
||||
/**
|
||||
* Checks whether a number is a prime.
|
||||
*
|
||||
* @param \GMP $n
|
||||
* @return boolean
|
||||
*/
|
||||
public function isPrime(\GMP $n): bool;
|
||||
|
||||
/**
|
||||
* Gets the next known prime that is greater than a given prime.
|
||||
*
|
||||
* @param \GMP $currentPrime
|
||||
* @return \GMP
|
||||
*/
|
||||
public function nextPrime(\GMP $currentPrime): \GMP;
|
||||
|
||||
/**
|
||||
* @param \GMP $a
|
||||
* @param \GMP $m
|
||||
* @return \GMP
|
||||
*/
|
||||
public function inverseMod(\GMP $a, \GMP $m): \GMP;
|
||||
|
||||
/**
|
||||
* @param \GMP $a
|
||||
* @param \GMP $p
|
||||
* @return int
|
||||
*/
|
||||
public function jacobi(\GMP $a, \GMP $p): int;
|
||||
|
||||
/**
|
||||
* @param \GMP $x
|
||||
* @return string
|
||||
*/
|
||||
public function intToString(\GMP $x): string;
|
||||
|
||||
/**
|
||||
* @param \GMP $x
|
||||
* @param int $byteSize
|
||||
* @return string
|
||||
*/
|
||||
public function intToFixedSizeString(\GMP $x, int $byteSize): string;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int|string $s
|
||||
* @return \GMP
|
||||
*/
|
||||
public function stringToInt(string $s): \GMP;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \GMP $m
|
||||
* @return \GMP
|
||||
*/
|
||||
public function digestInteger(\GMP $m): \GMP;
|
||||
|
||||
/**
|
||||
* @param \GMP $a
|
||||
* @param \GMP $m
|
||||
* @return \GMP
|
||||
*/
|
||||
public function gcd2(\GMP $a, \GMP $m): \GMP;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param int $fromBase
|
||||
* @param int $toBase
|
||||
* @return string
|
||||
*/
|
||||
public function baseConvert(string $value, int $fromBase, int $toBase): string;
|
||||
|
||||
/**
|
||||
* @return NumberTheory
|
||||
*/
|
||||
public function getNumberTheory(): NumberTheory;
|
||||
|
||||
/**
|
||||
* @param \GMP $modulus
|
||||
* @return ModularArithmetic
|
||||
*/
|
||||
public function getModularArithmetic(\GMP $modulus): ModularArithmetic;
|
||||
}
|
||||
48
pgserver/vendor/mdanter/ecc/src/Math/MathAdapterFactory.php
vendored
Normal file
48
pgserver/vendor/mdanter/ecc/src/Math/MathAdapterFactory.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Mdanter\Ecc\Math;
|
||||
|
||||
class MathAdapterFactory
|
||||
{
|
||||
/**
|
||||
* @var GmpMathInterface
|
||||
*/
|
||||
private static $forcedAdapter = null;
|
||||
|
||||
/**
|
||||
* @param GmpMathInterface $adapter
|
||||
*/
|
||||
public static function forceAdapter(GmpMathInterface $adapter = null)
|
||||
{
|
||||
self::$forcedAdapter = $adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $debug
|
||||
* @return DebugDecorator|GmpMathInterface|null
|
||||
*/
|
||||
public static function getAdapter(bool $debug = false): GmpMathInterface
|
||||
{
|
||||
if (self::$forcedAdapter !== null) {
|
||||
return self::$forcedAdapter;
|
||||
}
|
||||
|
||||
$adapter = new GmpMath();
|
||||
|
||||
return self::wrapAdapter($adapter, $debug);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GmpMathInterface $adapter
|
||||
* @param bool $debug
|
||||
* @return DebugDecorator|GmpMathInterface
|
||||
*/
|
||||
private static function wrapAdapter(GmpMathInterface $adapter, bool $debug): GmpMathInterface
|
||||
{
|
||||
if ($debug === true) {
|
||||
return new DebugDecorator($adapter);
|
||||
}
|
||||
|
||||
return $adapter;
|
||||
}
|
||||
}
|
||||
76
pgserver/vendor/mdanter/ecc/src/Math/ModularArithmetic.php
vendored
Normal file
76
pgserver/vendor/mdanter/ecc/src/Math/ModularArithmetic.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Mdanter\Ecc\Math;
|
||||
|
||||
class ModularArithmetic
|
||||
{
|
||||
/**
|
||||
* @var GmpMathInterface
|
||||
*/
|
||||
private $adapter;
|
||||
|
||||
/**
|
||||
* @var \GMP
|
||||
*/
|
||||
private $modulus;
|
||||
|
||||
/**
|
||||
* @param GmpMathInterface $adapter
|
||||
* @param \GMP $modulus
|
||||
*/
|
||||
public function __construct(GmpMathInterface $adapter, \GMP $modulus)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
$this->modulus = $modulus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $augend
|
||||
* @param \GMP $addend
|
||||
* @return \GMP
|
||||
*/
|
||||
public function add(\GMP $augend, \GMP $addend): \GMP
|
||||
{
|
||||
return $this->adapter->mod($this->adapter->add($augend, $addend), $this->modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $minuend
|
||||
* @param \GMP $subtrahend
|
||||
* @return \GMP
|
||||
*/
|
||||
public function sub(\GMP $minuend, \GMP $subtrahend): \GMP
|
||||
{
|
||||
return $this->adapter->mod($this->adapter->sub($minuend, $subtrahend), $this->modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $multiplier
|
||||
* @param \GMP $muliplicand
|
||||
* @return \GMP
|
||||
*/
|
||||
public function mul(\GMP $multiplier, \GMP $muliplicand): \GMP
|
||||
{
|
||||
return $this->adapter->mod($this->adapter->mul($multiplier, $muliplicand), $this->modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $dividend
|
||||
* @param \GMP $divisor
|
||||
* @return \GMP
|
||||
*/
|
||||
public function div(\GMP $dividend, \GMP $divisor): \GMP
|
||||
{
|
||||
return $this->mul($dividend, $this->adapter->inverseMod($divisor, $this->modulus));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $base
|
||||
* @param \GMP $exponent
|
||||
* @return \GMP
|
||||
*/
|
||||
public function pow(\GMP $base, \GMP $exponent): \GMP
|
||||
{
|
||||
return $this->adapter->powmod($base, $exponent, $this->modulus);
|
||||
}
|
||||
}
|
||||
267
pgserver/vendor/mdanter/ecc/src/Math/NumberTheory.php
vendored
Normal file
267
pgserver/vendor/mdanter/ecc/src/Math/NumberTheory.php
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
namespace Mdanter\Ecc\Math;
|
||||
|
||||
/***********************************************************************
|
||||
* Copyright (C) 2012 Matyas Danter
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Implementation of some number theoretic algorithms
|
||||
*
|
||||
* @author Matyas Danter
|
||||
*/
|
||||
|
||||
use Mdanter\Ecc\Exception\NumberTheoryException;
|
||||
use Mdanter\Ecc\Exception\SquareRootException;
|
||||
|
||||
/**
|
||||
* Rewritten to take a MathAdaptor to handle different environments. Has
|
||||
* some desireable functions for public key compression/recovery.
|
||||
*/
|
||||
class NumberTheory
|
||||
{
|
||||
/**
|
||||
* @var GmpMathInterface
|
||||
*/
|
||||
private $adapter;
|
||||
|
||||
/**
|
||||
* @param GmpMathInterface $adapter
|
||||
*/
|
||||
public function __construct(GmpMathInterface $adapter)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
$this->zero = gmp_init(0, 10);
|
||||
$this->one = gmp_init(1, 10);
|
||||
$this->two = gmp_init(2, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP[] $poly
|
||||
* @param \GMP[] $polymod
|
||||
* @param \GMP $p
|
||||
* @return \GMP[]
|
||||
*/
|
||||
public function polynomialReduceMod(array $poly, array $polymod, \GMP $p): array
|
||||
{
|
||||
$adapter = $this->adapter;
|
||||
|
||||
// Only enter if last value is set, implying count > 0
|
||||
if ((($last = end($polymod)) instanceof \GMP) && $adapter->equals($last, $this->one)) {
|
||||
$count_polymod = count($polymod);
|
||||
while (count($poly) >= $count_polymod) {
|
||||
if (!$adapter->equals(end($poly), $this->zero)) {
|
||||
for ($i = 2; $i < $count_polymod + 1; $i++) {
|
||||
$poly[count($poly) - $i] =
|
||||
$adapter->mod(
|
||||
$adapter->sub(
|
||||
$poly[count($poly) - $i],
|
||||
$adapter->mul(
|
||||
end($poly),
|
||||
$polymod[$count_polymod - $i]
|
||||
)
|
||||
),
|
||||
$p
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$poly = array_slice($poly, 0, count($poly) - 1);
|
||||
}
|
||||
|
||||
return $poly;
|
||||
}
|
||||
|
||||
throw new NumberTheoryException('Unable to calculate polynomialReduceMod');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP[] $m1
|
||||
* @param \GMP[] $m2
|
||||
* @param \GMP[] $polymod
|
||||
* @param \GMP $p
|
||||
* @return \GMP[]
|
||||
*/
|
||||
public function polynomialMultiplyMod(array $m1, array $m2, array $polymod, \GMP $p): array
|
||||
{
|
||||
$prod = array();
|
||||
$cm1 = count($m1);
|
||||
$cm2 = count($m2);
|
||||
|
||||
for ($i = 0; $i < $cm1; $i++) {
|
||||
for ($j = 0; $j < $cm2; $j++) {
|
||||
$index = $i + $j;
|
||||
if (!isset($prod[$index])) {
|
||||
$prod[$index] = $this->zero;
|
||||
}
|
||||
$prod[$index] =
|
||||
$this->adapter->mod(
|
||||
$this->adapter->add(
|
||||
$prod[$index],
|
||||
$this->adapter->mul(
|
||||
$m1[$i],
|
||||
$m2[$j]
|
||||
)
|
||||
),
|
||||
$p
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->polynomialReduceMod($prod, $polymod, $p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP[] $base
|
||||
* @param \GMP $exponent
|
||||
* @param \GMP[] $polymod
|
||||
* @param \GMP $p
|
||||
* @return \GMP[]
|
||||
*/
|
||||
public function polynomialPowMod(array $base, \GMP $exponent, array $polymod, \GMP $p): array
|
||||
{
|
||||
$adapter = $this->adapter;
|
||||
|
||||
if ($adapter->cmp($exponent, $p) < 0) {
|
||||
if ($adapter->equals($exponent, $this->zero)) {
|
||||
return $this->one;
|
||||
}
|
||||
|
||||
$G = $base;
|
||||
$k = $exponent;
|
||||
|
||||
if ($adapter->equals($adapter->mod($k, $this->two), $this->one)) {
|
||||
$s = $G;
|
||||
} else {
|
||||
$s = array($this->one);
|
||||
}
|
||||
|
||||
while ($adapter->cmp($k, $this->one) > 0) {
|
||||
$k = $adapter->div($k, $this->two);
|
||||
|
||||
$G = $this->polynomialMultiplyMod($G, $G, $polymod, $p);
|
||||
if ($adapter->equals($adapter->mod($k, $this->two), $this->one)) {
|
||||
$s = $this->polynomialMultiplyMod($G, $s, $polymod, $p);
|
||||
}
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
throw new NumberTheoryException('Unable to calculate polynomialPowMod');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GMP $a
|
||||
* @param \GMP $p
|
||||
* @return \GMP
|
||||
*/
|
||||
public function squareRootModP(\GMP $a, \GMP $p): \GMP
|
||||
{
|
||||
$math = $this->adapter;
|
||||
$four = gmp_init(4, 10);
|
||||
$eight = gmp_init(8, 10);
|
||||
|
||||
$modMath = $math->getModularArithmetic($p);
|
||||
if ($math->cmp($this->one, $p) < 0) {
|
||||
if ($math->equals($a, $this->zero)) {
|
||||
return $this->zero;
|
||||
}
|
||||
|
||||
if ($math->equals($p, $this->two)) {
|
||||
return $a;
|
||||
}
|
||||
|
||||
$jac = $math->jacobi($a, $p);
|
||||
if ($jac === -1) {
|
||||
throw new SquareRootException("{$math->toString($a)} has no square root modulo {$math->toString($p)}");
|
||||
}
|
||||
|
||||
if ($math->equals($math->mod($p, $four), gmp_init(3, 10))) {
|
||||
return $modMath->pow($a, $math->div($math->add($p, $this->one), $four));
|
||||
}
|
||||
|
||||
if ($math->equals($math->mod($p, $eight), gmp_init(5, 10))) {
|
||||
$d = $modMath->pow($a, $math->div($math->sub($p, $this->one), $four));
|
||||
if ($math->equals($d, $this->one)) {
|
||||
return $modMath->pow($a, $math->div($math->add($p, gmp_init(3, 10)), $eight));
|
||||
}
|
||||
|
||||
if ($math->equals($d, $math->sub($p, $this->one))) {
|
||||
return $modMath->mul(
|
||||
$math->mul(
|
||||
$this->two,
|
||||
$a
|
||||
),
|
||||
$modMath->pow(
|
||||
$math->mul(
|
||||
$four,
|
||||
$a
|
||||
),
|
||||
$math->div(
|
||||
$math->sub(
|
||||
$p,
|
||||
gmp_init(5, 10)
|
||||
),
|
||||
$eight
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
//shouldn't get here
|
||||
}
|
||||
|
||||
for ($b = $this->two; $math->cmp($b, $p) < 0; $b = gmp_add($b, $this->one)) {
|
||||
if ($math->jacobi(
|
||||
$math->sub(
|
||||
$math->mul($b, $b),
|
||||
$math->mul($four, $a)
|
||||
),
|
||||
$p
|
||||
) == -1
|
||||
) {
|
||||
$f = array($a, $math->sub($this->zero, $b), $this->one);
|
||||
|
||||
$ff = $this->polynomialPowMod(
|
||||
array($this->zero, $this->one),
|
||||
$math->div(
|
||||
$math->add(
|
||||
$p,
|
||||
$this->one
|
||||
),
|
||||
$this->two
|
||||
),
|
||||
$f,
|
||||
$p
|
||||
);
|
||||
|
||||
if ($math->equals($ff[1], $this->zero)) {
|
||||
return $ff[0];
|
||||
}
|
||||
// if we got here no b was found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new SquareRootException('Unable to calculate square root mod p!');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user