Subversion Repositories oidplus

Rev

Rev 846 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /**
  4.  * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
  5.  *
  6.  * http://www.secg.org/SEC2-Ver-1.0.pdf provides for curves with custom parameters.
  7.  * ie. the coefficients can be arbitrary set through specially formatted keys, etc.
  8.  * As such, Prime.php is built very generically and it's not able to take full
  9.  * advantage of curves with 0 coefficients to produce simplified point doubling,
  10.  * point addition. Twisted Edwards curves, in contrast, do not have a way, currently,
  11.  * to customize them. As such, we can omit the super generic stuff from this class
  12.  * and let the named curves (Ed25519 and Ed448) define their own custom tailored
  13.  * point addition and point doubling methods.
  14.  *
  15.  * More info:
  16.  *
  17.  * https://en.wikipedia.org/wiki/Twisted_Edwards_curve
  18.  *
  19.  * PHP version 5 and 7
  20.  *
  21.  * @category  Crypt
  22.  * @package   EC
  23.  * @author    Jim Wigginton <terrafrost@php.net>
  24.  * @copyright 2017 Jim Wigginton
  25.  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  26.  * @link      http://pear.php.net/package/Math_BigInteger
  27.  */
  28.  
  29. namespace phpseclib3\Crypt\EC\BaseCurves;
  30.  
  31. use phpseclib3\Math\BigInteger;
  32. use phpseclib3\Math\PrimeField;
  33. use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
  34.  
  35. /**
  36.  * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
  37.  *
  38.  * @package Prime
  39.  * @author  Jim Wigginton <terrafrost@php.net>
  40.  * @access  public
  41.  */
  42. class TwistedEdwards extends Base
  43. {
  44.     /**
  45.      * The modulo
  46.      *
  47.      * @var BigInteger
  48.      */
  49.     protected $modulo;
  50.  
  51.     /**
  52.      * Cofficient for x^2
  53.      *
  54.      * @var object
  55.      */
  56.     protected $a;
  57.  
  58.     /**
  59.      * Cofficient for x^2*y^2
  60.      *
  61.      * @var object
  62.      */
  63.     protected $d;
  64.  
  65.     /**
  66.      * Base Point
  67.      *
  68.      * @var object[]
  69.      */
  70.     protected $p;
  71.  
  72.     /**
  73.      * The number zero over the specified finite field
  74.      *
  75.      * @var object
  76.      */
  77.     protected $zero;
  78.  
  79.     /**
  80.      * The number one over the specified finite field
  81.      *
  82.      * @var object
  83.      */
  84.     protected $one;
  85.  
  86.     /**
  87.      * The number two over the specified finite field
  88.      *
  89.      * @var object
  90.      */
  91.     protected $two;
  92.  
  93.     /**
  94.      * Sets the modulo
  95.      */
  96.     public function setModulo(BigInteger $modulo)
  97.     {
  98.         $this->modulo = $modulo;
  99.         $this->factory = new PrimeField($modulo);
  100.         $this->zero = $this->factory->newInteger(new BigInteger(0));
  101.         $this->one = $this->factory->newInteger(new BigInteger(1));
  102.         $this->two = $this->factory->newInteger(new BigInteger(2));
  103.     }
  104.  
  105.     /**
  106.      * Set coefficients a and b
  107.      */
  108.     public function setCoefficients(BigInteger $a, BigInteger $d)
  109.     {
  110.         if (!isset($this->factory)) {
  111.             throw new \RuntimeException('setModulo needs to be called before this method');
  112.         }
  113.         $this->a = $this->factory->newInteger($a);
  114.         $this->d = $this->factory->newInteger($d);
  115.     }
  116.  
  117.     /**
  118.      * Set x and y coordinates for the base point
  119.      */
  120.     public function setBasePoint($x, $y)
  121.     {
  122.         switch (true) {
  123.             case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
  124.                 throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer');
  125.             case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
  126.                 throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer');
  127.         }
  128.         if (!isset($this->factory)) {
  129.             throw new \RuntimeException('setModulo needs to be called before this method');
  130.         }
  131.         $this->p = [
  132.             $x instanceof BigInteger ? $this->factory->newInteger($x) : $x,
  133.             $y instanceof BigInteger ? $this->factory->newInteger($y) : $y
  134.         ];
  135.     }
  136.  
  137.     /**
  138.      * Returns the a coefficient
  139.      *
  140.      * @return \phpseclib3\Math\PrimeField\Integer
  141.      */
  142.     public function getA()
  143.     {
  144.         return $this->a;
  145.     }
  146.  
  147.     /**
  148.      * Returns the a coefficient
  149.      *
  150.      * @return \phpseclib3\Math\PrimeField\Integer
  151.      */
  152.     public function getD()
  153.     {
  154.         return $this->d;
  155.     }
  156.  
  157.     /**
  158.      * Retrieve the base point as an array
  159.      *
  160.      * @return array
  161.      */
  162.     public function getBasePoint()
  163.     {
  164.         if (!isset($this->factory)) {
  165.             throw new \RuntimeException('setModulo needs to be called before this method');
  166.         }
  167.         /*
  168.         if (!isset($this->p)) {
  169.             throw new \RuntimeException('setBasePoint needs to be called before this method');
  170.         }
  171.         */
  172.         return $this->p;
  173.     }
  174.  
  175.     /**
  176.      * Returns the affine point
  177.      *
  178.      * @return \phpseclib3\Math\PrimeField\Integer[]
  179.      */
  180.     public function convertToAffine(array $p)
  181.     {
  182.         if (!isset($p[2])) {
  183.             return $p;
  184.         }
  185.         list($x, $y, $z) = $p;
  186.         $z = $this->one->divide($z);
  187.         return [
  188.             $x->multiply($z),
  189.             $y->multiply($z)
  190.         ];
  191.     }
  192.  
  193.     /**
  194.      * Returns the modulo
  195.      *
  196.      * @return \phpseclib3\Math\BigInteger
  197.      */
  198.     public function getModulo()
  199.     {
  200.         return $this->modulo;
  201.     }
  202.  
  203.     /**
  204.      * Tests whether or not the x / y values satisfy the equation
  205.      *
  206.      * @return boolean
  207.      */
  208.     public function verifyPoint(array $p)
  209.     {
  210.         list($x, $y) = $p;
  211.         $x2 = $x->multiply($x);
  212.         $y2 = $y->multiply($y);
  213.  
  214.         $lhs = $this->a->multiply($x2)->add($y2);
  215.         $rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one);
  216.  
  217.         return $lhs->equals($rhs);
  218.     }
  219. }
  220.