1<?php
2
3/**
4 * Curve448
5 *
6 * PHP version 5 and 7
7 *
8 * @category  Crypt
9 * @package   EC
10 * @author    Jim Wigginton <terrafrost@php.net>
11 * @copyright 2019 Jim Wigginton
12 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
13 * @link      http://pear.php.net/package/Math_BigInteger
14 */
15
16namespace phpseclib3\Crypt\EC\Curves;
17
18use phpseclib3\Crypt\EC\BaseCurves\Montgomery;
19use phpseclib3\Math\BigInteger;
20
21class Curve448 extends Montgomery
22{
23    public function __construct()
24    {
25        // 2^448 - 2^224 - 1
26        $this->setModulo(new BigInteger(
27            'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' .
28            'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
29            16
30        ));
31        $this->a24 = $this->factory->newInteger(new BigInteger('39081'));
32        $this->p = [$this->factory->newInteger(new BigInteger(5))];
33        // 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
34        $this->setOrder(new BigInteger(
35            '3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
36            '7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3',
37            16
38        ));
39
40        /*
41        $this->setCoefficients(
42            new BigInteger('156326'), // a
43        );
44        $this->setBasePoint(
45            new BigInteger(5),
46            new BigInteger(
47                '355293926785568175264127502063783334808976399387714271831880898' .
48                '435169088786967410002932673765864550910142774147268105838985595290' .
49                '606362')
50        );
51        */
52    }
53
54    /**
55     * Multiply a point on the curve by a scalar
56     *
57     * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
58     *
59     * @return array
60     */
61    public function multiplyPoint(array $p, BigInteger $d)
62    {
63        //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
64        //return [$this->factory->newInteger(new BigInteger($r, 256))];
65
66        $d = $d->toBytes();
67        $d[0] = $d[0] & "\xFC";
68        $d = strrev($d);
69        $d |= "\x80";
70        $d = new BigInteger($d, 256);
71
72        return parent::multiplyPoint($p, $d);
73    }
74
75    /**
76     * Creates a random scalar multiplier
77     *
78     * @return BigInteger
79     */
80    public function createRandomMultiplier()
81    {
82        return BigInteger::random(446);
83    }
84
85    /**
86     * Performs range check
87     */
88    public function rangeCheck(BigInteger $x)
89    {
90        if ($x->getLength() > 448 || $x->isNegative()) {
91            throw new \RangeException('x must be a positive integer less than 446 bytes in length');
92        }
93    }
94}
95