Subversion Repositories oidplus

Rev

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

Rev Author Line No. Line
827 daniel-mar 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
 *
874 daniel-mar 21
 * @category  Crypt
22
 * @package   EC
827 daniel-mar 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
 *
874 daniel-mar 38
 * @package Prime
827 daniel-mar 39
 * @author  Jim Wigginton <terrafrost@php.net>
874 daniel-mar 40
 * @access  public
827 daniel-mar 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
}