pssht  latest
SSH server library written in PHP
Curve25519.php
1 <?php
2 
3 /*
4 * This file is part of pssht.
5 *
6 * (c) François Poirotte <clicky@erebot.net>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 
12 namespace fpoirotte\Pssht\ECC;
13 
27 {
29  protected static $instance = null;
30 
32  protected $p;
33 
34  protected function __construct()
35  {
36  $this->p = gmp_init('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16);
37  }
38 
39  public static function getInstance()
40  {
41  if (self::$instance === null) {
42  self::$instance = new static();
43  }
44  return self::$instance;
45  }
46 
47  protected function doubleAndAdd($P2, $P3, $X1)
48  {
49  list($X2, $Z2) = $P2;
50  list($X3, $Z3) = $P3;
51  $a24 = gmp_init(121666);
52 
53  $A = gmp_add($X2, $Z2);
54  $AA = gmp_mod(gmp_mul($A, $A), $this->p);
55  $B = gmp_add(gmp_sub($X2, $Z2), $this->p);
56  $BB = gmp_mod(gmp_mul($B, $B), $this->p);
57  $E = gmp_mod(gmp_add(gmp_sub($AA, $BB), $this->p), $this->p);
58  $C = gmp_add($X3, $Z3);
59  $D = gmp_add(gmp_sub($X3, $Z3), $this->p);
60  $DA = gmp_mod(gmp_mul($D, $A), $this->p);
61  $CB = gmp_mod(gmp_mul($C, $B), $this->p);
62  $t = gmp_add($DA, $CB);
63  $X5 = gmp_mod(gmp_mul($t, $t), $this->p);
64  $t = gmp_add(gmp_sub($DA, $CB), $this->p);
65  $Z5 = gmp_mod(gmp_mul($X1, gmp_mul($t, $t)), $this->p);
66  $X4 = gmp_mod(gmp_mul($AA, $BB), $this->p);
67  $Z4 = gmp_mod(gmp_mul($E, gmp_add($BB, gmp_mul($a24, $E))), $this->p);
68  return array(array($X4, $Z4), array($X5, $Z5));
69  }
70 
71  protected function scalarmult($X, $N)
72  {
73  if (!((is_resource($X) && get_resource_type($X) === 'GMP integer') ||
74  (is_object($X) && ($X instanceof \GMP)))) {
75  throw new \InvalidArgumentException();
76  }
77 
78  if (!((is_resource($N) && get_resource_type($N) === 'GMP integer') ||
79  (is_object($N) && ($N instanceof \GMP)))) {
80  throw new \InvalidArgumentException();
81  }
82 
83  $b = str_pad(strrev(gmp_strval($N, 2)), 256, '0');
84  $P1 = array(1, 0);
85  $P2 = array($X, 1);
86 
87  for ($i = 255; $i >= 0; $i--) {
88  if ($b[$i] === '1') {
89  list($P2, $P1) = $this->doubleAndAdd($P2, $P1, $X);
90  } else {
91  list($P1, $P2) = $this->doubleAndAdd($P1, $P2, $X);
92  }
93  }
94  return $P1;
95  }
96 
97  protected function pubkeyToPoint($public)
98  {
99  if (!is_string($public) || strlen($public) !== 32) {
100  throw new \InvalidArgumentException();
101  }
102 
103  return array(
104  gmp_init(bin2hex($public), 16),
105  1
106  );
107  }
108 
109  protected function pointToPubkey($P)
110  {
111  list($X, $Z) = $P;
112  $Zinv = gmp_powm($Z, gmp_sub($this->p, 2), $this->p);
113  $x1 = gmp_mod(gmp_mul($X, $Zinv), $this->p);
114  $res = str_pad(gmp_strval($x1, 16), 64, '0', STR_PAD_LEFT);
115  return strrev(pack('H*', $res));
116  }
117 
118  public function getPublic($S)
119  {
120  return $this->getShared($S, $this->pointToPubkey(array(9, 1)));
121  }
122 
123  public function getShared($S, $P)
124  {
125  if (!is_string($S) || strlen($S) !== 32) {
126  throw new \InvalidArgumentException();
127  }
128 
129  // Clamp the secret key.
130  $n = gmp_init(bin2hex(strrev($S)), 16);
131  $n = gmp_and(
132  gmp_or($n, 64),
133  gmp_init(
134  '7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8',
135  16
136  )
137  );
138 
139  $P0 = $this->pubkeyToPoint(strrev($P));
140  $P1 = $this->scalarmult($P0[0], $n);
141  $Q = $this->pointToPubkey($P1);
142  return $Q;
143  }
144 }
static $instance
Singleton instance.
Definition: Curve25519.php:29
$p
Set to 2**255 - 19, hence this curve&#39;s name.
Definition: Curve25519.php:32