34 protected function __construct()
36 $this->p = gmp_init(
'7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16);
39 public static function getInstance()
41 if (self::$instance === null) {
42 self::$instance =
new static();
44 return self::$instance;
47 protected function doubleAndAdd($P2, $P3, $X1)
51 $a24 = gmp_init(121666);
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));
71 protected function scalarmult($X, $N)
73 if (!((is_resource($X) && get_resource_type($X) ===
'GMP integer') ||
74 (is_object($X) && ($X instanceof \GMP)))) {
75 throw new \InvalidArgumentException();
78 if (!((is_resource($N) && get_resource_type($N) ===
'GMP integer') ||
79 (is_object($N) && ($N instanceof \GMP)))) {
80 throw new \InvalidArgumentException();
83 $b = str_pad(strrev(gmp_strval($N, 2)), 256,
'0');
87 for ($i = 255; $i >= 0; $i--) {
89 list($P2, $P1) = $this->doubleAndAdd($P2, $P1, $X);
91 list($P1, $P2) = $this->doubleAndAdd($P1, $P2, $X);
97 protected function pubkeyToPoint($public)
99 if (!is_string($public) || strlen($public) !== 32) {
100 throw new \InvalidArgumentException();
104 gmp_init(bin2hex($public), 16),
109 protected function pointToPubkey($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));
118 public function getPublic($S)
120 return $this->getShared($S, $this->pointToPubkey(array(9, 1)));
123 public function getShared($S, $P)
125 if (!is_string($S) || strlen($S) !== 32) {
126 throw new \InvalidArgumentException();
130 $n = gmp_init(bin2hex(strrev($S)), 16);
134 '7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8',
139 $P0 = $this->pubkeyToPoint(strrev($P));
140 $P1 = $this->scalarmult($P0[0], $n);
141 $Q = $this->pointToPubkey($P1);
static $instance
Singleton instance.
$p
Set to 2**255 - 19, hence this curve's name.