* @copyright 2017 Jim Wigginton * @license http://www.opensource.org/licenses/mit-license.html MIT License * @link http://pear.php.net/package/Math_BigInteger */ namespace phpseclib\Crypt\ECDSA\BaseCurves; use phpseclib\Math\PrimeField; use phpseclib\Math\BigInteger; use phpseclib\Math\PrimeField\Integer as PrimeInteger; /** * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2 * * @package Prime * @author Jim Wigginton * @access public */ class TwistedEdwards extends Base { /** * The modulo * * @var BigInteger */ protected $modulo; /** * Cofficient for x^2 * * @var object */ protected $a; /** * Cofficient for x^2*y^2 * * @var object */ protected $d; /** * Base Point * * @var object[] */ protected $p; /** * The number zero over the specified finite field * * @var object */ protected $zero; /** * The number one over the specified finite field * * @var object */ protected $one; /** * The number two over the specified finite field * * @var object */ protected $two; /** * Sets the modulo */ public function setModulo(BigInteger $modulo) { $this->modulo = $modulo; $this->factory = new PrimeField($modulo); $this->zero = $this->factory->newInteger(new BigInteger(0)); $this->one = $this->factory->newInteger(new BigInteger(1)); $this->two = $this->factory->newInteger(new BigInteger(2)); } /** * Set coefficients a and b */ public function setCoefficients(BigInteger $a, BigInteger $d) { if (!isset($this->factory)) { throw new \RuntimeException('setModulo needs to be called before this method'); } $this->a = $this->factory->newInteger($a); $this->d = $this->factory->newInteger($d); } /** * Set x and y coordinates for the base point */ public function setBasePoint($x, $y) { switch (true) { case !$x instanceof BigInteger && !$x instanceof PrimeInteger: throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); case !$y instanceof BigInteger && !$y instanceof PrimeInteger: throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); } if (!isset($this->factory)) { throw new \RuntimeException('setModulo needs to be called before this method'); } $this->p = [ $x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y ]; } /** * Returns the a coefficient * * @return \phpseclib\Math\PrimeField\Integer */ public function getA() { return $this->a; } /** * Returns the a coefficient * * @return \phpseclib\Math\PrimeField\Integer */ public function getD() { return $this->d; } /** * Retrieve the base point as an array * * @return array */ public function getBasePoint() { if (!isset($this->factory)) { throw new \RuntimeException('setModulo needs to be called before this method'); } /* if (!isset($this->p)) { throw new \RuntimeException('setBasePoint needs to be called before this method'); } */ return $this->p; } /** * Returns the affine point * * @return \phpseclib\Math\PrimeField\Integer[] */ public function convertToAffine(array $p) { if (!isset($p[2])) { return $p; } list($x, $y, $z) = $p; $z = $this->one->divide($z); return [ $x->multiply($z), $y->multiply($z) ]; } /** * Returns the modulo * * @return \phpseclib\Math\BigInteger */ public function getModulo() { return $this->modulo; } /** * Tests whether or not the x / y values satisfy the equation * * @return boolean */ public function verifyPoint(array $p) { list($x, $y) = $p; $x2 = $x->multiply($x); $y2 = $y->multiply($y); $lhs = $this->a->multiply($x2)->add($y2); $rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one); return $lhs->equals($rhs); } /** * Tests whether or not the x / y values satisfy the equation * * @return boolean */ public function get(array $p) { list($x, $y) = $p; $x2 = $x->multiply($x); $y2 = $y->multiply($y); $lhs = $this->a->multiply($x2)->add($y2); $rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one); return $lhs->equals($rhs); } }