xref: /dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php (revision 850e662095111529d7d330745fee3207907c4aee)
1<?php
2
3/**
4 * Curve methods common to all curves
5 *
6 * PHP version 5 and 7
7 *
8 * @author    Jim Wigginton <terrafrost@php.net>
9 * @copyright 2017 Jim Wigginton
10 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
11 * @link      http://pear.php.net/package/Math_BigInteger
12 */
13
14namespace phpseclib3\Crypt\EC\BaseCurves;
15
16use phpseclib3\Math\BigInteger;
17
18/**
19 * Base
20 *
21 * @author  Jim Wigginton <terrafrost@php.net>
22 */
23abstract class Base
24{
25    /**
26     * The Order
27     *
28     * @var BigInteger
29     */
30    protected $order;
31
32    /**
33     * Finite Field Integer factory
34     *
35     * @var FiniteField\Integer
36     */
37    protected $factory;
38
39    /**
40     * Returns a random integer
41     *
42     * @return object
43     */
44    public function randomInteger()
45    {
46        return $this->factory->randomInteger();
47    }
48
49    /**
50     * Converts a BigInteger to a FiniteField\Integer integer
51     *
52     * @return object
53     */
54    public function convertInteger(BigInteger $x)
55    {
56        return $this->factory->newInteger($x);
57    }
58
59    /**
60     * Returns the length, in bytes, of the modulo
61     *
62     * @return integer
63     */
64    public function getLengthInBytes()
65    {
66        return $this->factory->getLengthInBytes();
67    }
68
69    /**
70     * Returns the length, in bits, of the modulo
71     *
72     * @return integer
73     */
74    public function getLength()
75    {
76        return $this->factory->getLength();
77    }
78
79    /**
80     * Multiply a point on the curve by a scalar
81     *
82     * Uses the montgomery ladder technique as described here:
83     *
84     * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder
85     * https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772
86     *
87     * @return array
88     */
89    public function multiplyPoint(array $p, BigInteger $d)
90    {
91        $alreadyInternal = isset($p[2]);
92        $r = $alreadyInternal ?
93            [[], $p] :
94            [[], $this->convertToInternal($p)];
95
96        $d = $d->toBits();
97        for ($i = 0; $i < strlen($d); $i++) {
98            $d_i = (int) $d[$i];
99            $r[1 - $d_i] = $this->addPoint($r[0], $r[1]);
100            $r[$d_i] = $this->doublePoint($r[$d_i]);
101        }
102
103        return $alreadyInternal ? $r[0] : $this->convertToAffine($r[0]);
104    }
105
106    /**
107     * Creates a random scalar multiplier
108     *
109     * @return BigInteger
110     */
111    public function createRandomMultiplier()
112    {
113        static $one;
114        if (!isset($one)) {
115            $one = new BigInteger(1);
116        }
117
118        return BigInteger::randomRange($one, $this->order->subtract($one));
119    }
120
121    /**
122     * Performs range check
123     */
124    public function rangeCheck(BigInteger $x)
125    {
126        static $zero;
127        if (!isset($zero)) {
128            $zero = new BigInteger();
129        }
130
131        if (!isset($this->order)) {
132            throw new \RuntimeException('setOrder needs to be called before this method');
133        }
134        if ($x->compare($this->order) > 0 || $x->compare($zero) <= 0) {
135            throw new \RangeException('x must be between 1 and the order of the curve');
136        }
137    }
138
139    /**
140     * Sets the Order
141     */
142    public function setOrder(BigInteger $order)
143    {
144        $this->order = $order;
145    }
146
147    /**
148     * Returns the Order
149     *
150     * @return BigInteger
151     */
152    public function getOrder()
153    {
154        return $this->order;
155    }
156
157    /**
158     * Use a custom defined modular reduction function
159     *
160     * @return object
161     */
162    public function setReduction(callable $func)
163    {
164        $this->factory->setReduction($func);
165    }
166
167    /**
168     * Returns the affine point
169     *
170     * @return object[]
171     */
172    public function convertToAffine(array $p)
173    {
174        return $p;
175    }
176
177    /**
178     * Converts an affine point to a jacobian coordinate
179     *
180     * @return object[]
181     */
182    public function convertToInternal(array $p)
183    {
184        return $p;
185    }
186
187    /**
188     * Negates a point
189     *
190     * @return object[]
191     */
192    public function negatePoint(array $p)
193    {
194        $temp = [
195            $p[0],
196            $p[1]->negate()
197        ];
198        if (isset($p[2])) {
199            $temp[] = $p[2];
200        }
201        return $temp;
202    }
203
204    /**
205     * Multiply and Add Points
206     *
207     * @return int[]
208     */
209    public function multiplyAddPoints(array $points, array $scalars)
210    {
211        $p1 = $this->convertToInternal($points[0]);
212        $p2 = $this->convertToInternal($points[1]);
213        $p1 = $this->multiplyPoint($p1, $scalars[0]);
214        $p2 = $this->multiplyPoint($p2, $scalars[1]);
215        $r = $this->addPoint($p1, $p2);
216        return $this->convertToAffine($r);
217    }
218}
219