1<?php
2
3/**
4 * Curve25519
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 Curve25519 extends Montgomery
22{
23    public function __construct()
24    {
25        // 2^255 - 19
26        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16));
27        $this->a24 = $this->factory->newInteger(new BigInteger('121666'));
28        $this->p = [$this->factory->newInteger(new BigInteger(9))];
29        // 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed
30        $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16));
31
32        /*
33        $this->setCoefficients(
34            new BigInteger('486662'), // a
35        );
36        $this->setBasePoint(
37            new BigInteger(9),
38            new BigInteger('14781619447589544791020593568409986887264606134616475288964881837755586237401')
39        );
40        */
41    }
42
43    /**
44     * Multiply a point on the curve by a scalar
45     *
46     * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
47     *
48     * @return array
49     */
50    public function multiplyPoint(array $p, BigInteger $d)
51    {
52        //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
53        //return [$this->factory->newInteger(new BigInteger($r, 256))];
54
55        $d = $d->toBytes();
56        $d &= "\xF8" . str_repeat("\xFF", 30) . "\x7F";
57        $d = strrev($d);
58        $d |= "\x40";
59        $d = new BigInteger($d, -256);
60
61        return parent::multiplyPoint($p, $d);
62    }
63
64    /**
65     * Creates a random scalar multiplier
66     *
67     * @return BigInteger
68     */
69    public function createRandomMultiplier()
70    {
71        return BigInteger::random(256);
72    }
73
74    /**
75     * Performs range check
76     */
77    public function rangeCheck(BigInteger $x)
78    {
79        if ($x->getLength() > 256 || $x->isNegative()) {
80            throw new \RangeException('x must be a positive integer less than 256 bytes in length');
81        }
82    }
83}
84