9
|
1 |
<?php |
|
2 |
|
|
3 |
if (class_exists('ParagonIE_Sodium_Core32_X25519', false)) { |
|
4 |
return; |
|
5 |
} |
|
6 |
|
|
7 |
/** |
|
8 |
* Class ParagonIE_Sodium_Core32_X25519 |
|
9 |
*/ |
|
10 |
abstract class ParagonIE_Sodium_Core32_X25519 extends ParagonIE_Sodium_Core32_Curve25519 |
|
11 |
{ |
|
12 |
/** |
|
13 |
* Alters the objects passed to this method in place. |
|
14 |
* |
|
15 |
* @internal You should not use this directly from another application |
|
16 |
* |
|
17 |
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f |
|
18 |
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $g |
|
19 |
* @param int $b |
|
20 |
* @return void |
|
21 |
* @throws SodiumException |
|
22 |
* @throws TypeError |
|
23 |
* @psalm-suppress MixedMethodCall |
|
24 |
*/ |
|
25 |
public static function fe_cswap( |
|
26 |
ParagonIE_Sodium_Core32_Curve25519_Fe $f, |
|
27 |
ParagonIE_Sodium_Core32_Curve25519_Fe $g, |
|
28 |
$b = 0 |
|
29 |
) { |
|
30 |
$f0 = (int) $f[0]->toInt(); |
|
31 |
$f1 = (int) $f[1]->toInt(); |
|
32 |
$f2 = (int) $f[2]->toInt(); |
|
33 |
$f3 = (int) $f[3]->toInt(); |
|
34 |
$f4 = (int) $f[4]->toInt(); |
|
35 |
$f5 = (int) $f[5]->toInt(); |
|
36 |
$f6 = (int) $f[6]->toInt(); |
|
37 |
$f7 = (int) $f[7]->toInt(); |
|
38 |
$f8 = (int) $f[8]->toInt(); |
|
39 |
$f9 = (int) $f[9]->toInt(); |
|
40 |
$g0 = (int) $g[0]->toInt(); |
|
41 |
$g1 = (int) $g[1]->toInt(); |
|
42 |
$g2 = (int) $g[2]->toInt(); |
|
43 |
$g3 = (int) $g[3]->toInt(); |
|
44 |
$g4 = (int) $g[4]->toInt(); |
|
45 |
$g5 = (int) $g[5]->toInt(); |
|
46 |
$g6 = (int) $g[6]->toInt(); |
|
47 |
$g7 = (int) $g[7]->toInt(); |
|
48 |
$g8 = (int) $g[8]->toInt(); |
|
49 |
$g9 = (int) $g[9]->toInt(); |
|
50 |
$b = -$b; |
|
51 |
/** @var int $x0 */ |
|
52 |
$x0 = ($f0 ^ $g0) & $b; |
|
53 |
/** @var int $x1 */ |
|
54 |
$x1 = ($f1 ^ $g1) & $b; |
|
55 |
/** @var int $x2 */ |
|
56 |
$x2 = ($f2 ^ $g2) & $b; |
|
57 |
/** @var int $x3 */ |
|
58 |
$x3 = ($f3 ^ $g3) & $b; |
|
59 |
/** @var int $x4 */ |
|
60 |
$x4 = ($f4 ^ $g4) & $b; |
|
61 |
/** @var int $x5 */ |
|
62 |
$x5 = ($f5 ^ $g5) & $b; |
|
63 |
/** @var int $x6 */ |
|
64 |
$x6 = ($f6 ^ $g6) & $b; |
|
65 |
/** @var int $x7 */ |
|
66 |
$x7 = ($f7 ^ $g7) & $b; |
|
67 |
/** @var int $x8 */ |
|
68 |
$x8 = ($f8 ^ $g8) & $b; |
|
69 |
/** @var int $x9 */ |
|
70 |
$x9 = ($f9 ^ $g9) & $b; |
|
71 |
$f[0] = ParagonIE_Sodium_Core32_Int32::fromInt($f0 ^ $x0); |
|
72 |
$f[1] = ParagonIE_Sodium_Core32_Int32::fromInt($f1 ^ $x1); |
|
73 |
$f[2] = ParagonIE_Sodium_Core32_Int32::fromInt($f2 ^ $x2); |
|
74 |
$f[3] = ParagonIE_Sodium_Core32_Int32::fromInt($f3 ^ $x3); |
|
75 |
$f[4] = ParagonIE_Sodium_Core32_Int32::fromInt($f4 ^ $x4); |
|
76 |
$f[5] = ParagonIE_Sodium_Core32_Int32::fromInt($f5 ^ $x5); |
|
77 |
$f[6] = ParagonIE_Sodium_Core32_Int32::fromInt($f6 ^ $x6); |
|
78 |
$f[7] = ParagonIE_Sodium_Core32_Int32::fromInt($f7 ^ $x7); |
|
79 |
$f[8] = ParagonIE_Sodium_Core32_Int32::fromInt($f8 ^ $x8); |
|
80 |
$f[9] = ParagonIE_Sodium_Core32_Int32::fromInt($f9 ^ $x9); |
|
81 |
$g[0] = ParagonIE_Sodium_Core32_Int32::fromInt($g0 ^ $x0); |
|
82 |
$g[1] = ParagonIE_Sodium_Core32_Int32::fromInt($g1 ^ $x1); |
|
83 |
$g[2] = ParagonIE_Sodium_Core32_Int32::fromInt($g2 ^ $x2); |
|
84 |
$g[3] = ParagonIE_Sodium_Core32_Int32::fromInt($g3 ^ $x3); |
|
85 |
$g[4] = ParagonIE_Sodium_Core32_Int32::fromInt($g4 ^ $x4); |
|
86 |
$g[5] = ParagonIE_Sodium_Core32_Int32::fromInt($g5 ^ $x5); |
|
87 |
$g[6] = ParagonIE_Sodium_Core32_Int32::fromInt($g6 ^ $x6); |
|
88 |
$g[7] = ParagonIE_Sodium_Core32_Int32::fromInt($g7 ^ $x7); |
|
89 |
$g[8] = ParagonIE_Sodium_Core32_Int32::fromInt($g8 ^ $x8); |
|
90 |
$g[9] = ParagonIE_Sodium_Core32_Int32::fromInt($g9 ^ $x9); |
|
91 |
} |
|
92 |
|
|
93 |
/** |
|
94 |
* @internal You should not use this directly from another application |
|
95 |
* |
|
96 |
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f |
|
97 |
* @return ParagonIE_Sodium_Core32_Curve25519_Fe |
|
98 |
* @throws SodiumException |
|
99 |
* @throws TypeError |
|
100 |
* @psalm-suppress MixedAssignment |
|
101 |
* @psalm-suppress MixedMethodCall |
|
102 |
*/ |
|
103 |
public static function fe_mul121666(ParagonIE_Sodium_Core32_Curve25519_Fe $f) |
|
104 |
{ |
|
105 |
/** @var array<int, ParagonIE_Sodium_Core32_Int64> $h */ |
|
106 |
$h = array(); |
|
107 |
for ($i = 0; $i < 10; ++$i) { |
|
108 |
$h[$i] = $f[$i]->toInt64()->mulInt(121666, 17); |
|
109 |
} |
|
110 |
|
|
111 |
$carry9 = $h[9]->addInt(1 << 24)->shiftRight(25); |
|
112 |
$h[0] = $h[0]->addInt64($carry9->mulInt(19, 5)); |
|
113 |
$h[9] = $h[9]->subInt64($carry9->shiftLeft(25)); |
|
114 |
|
|
115 |
$carry1 = $h[1]->addInt(1 << 24)->shiftRight(25); |
|
116 |
$h[2] = $h[2]->addInt64($carry1); |
|
117 |
$h[1] = $h[1]->subInt64($carry1->shiftLeft(25)); |
|
118 |
|
|
119 |
$carry3 = $h[3]->addInt(1 << 24)->shiftRight(25); |
|
120 |
$h[4] = $h[4]->addInt64($carry3); |
|
121 |
$h[3] = $h[3]->subInt64($carry3->shiftLeft(25)); |
|
122 |
|
|
123 |
$carry5 = $h[5]->addInt(1 << 24)->shiftRight(25); |
|
124 |
$h[6] = $h[6]->addInt64($carry5); |
|
125 |
$h[5] = $h[5]->subInt64($carry5->shiftLeft(25)); |
|
126 |
|
|
127 |
$carry7 = $h[7]->addInt(1 << 24)->shiftRight(25); |
|
128 |
$h[8] = $h[8]->addInt64($carry7); |
|
129 |
$h[7] = $h[7]->subInt64($carry7->shiftLeft(25)); |
|
130 |
|
|
131 |
$carry0 = $h[0]->addInt(1 << 25)->shiftRight(26); |
|
132 |
$h[1] = $h[1]->addInt64($carry0); |
|
133 |
$h[0] = $h[0]->subInt64($carry0->shiftLeft(26)); |
|
134 |
|
|
135 |
$carry2 = $h[2]->addInt(1 << 25)->shiftRight(26); |
|
136 |
$h[3] = $h[3]->addInt64($carry2); |
|
137 |
$h[2] = $h[2]->subInt64($carry2->shiftLeft(26)); |
|
138 |
|
|
139 |
$carry4 = $h[4]->addInt(1 << 25)->shiftRight(26); |
|
140 |
$h[5] = $h[5]->addInt64($carry4); |
|
141 |
$h[4] = $h[4]->subInt64($carry4->shiftLeft(26)); |
|
142 |
|
|
143 |
$carry6 = $h[6]->addInt(1 << 25)->shiftRight(26); |
|
144 |
$h[7] = $h[7]->addInt64($carry6); |
|
145 |
$h[6] = $h[6]->subInt64($carry6->shiftLeft(26)); |
|
146 |
|
|
147 |
$carry8 = $h[8]->addInt(1 << 25)->shiftRight(26); |
|
148 |
$h[9] = $h[9]->addInt64($carry8); |
|
149 |
$h[8] = $h[8]->subInt64($carry8->shiftLeft(26)); |
|
150 |
|
|
151 |
for ($i = 0; $i < 10; ++$i) { |
|
152 |
$h[$i] = $h[$i]->toInt32(); |
|
153 |
} |
16
|
154 |
/** @var array<int, ParagonIE_Sodium_Core32_Int32> $h2 */ |
|
155 |
$h2 = $h; |
|
156 |
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h2); |
9
|
157 |
} |
|
158 |
|
|
159 |
/** |
|
160 |
* @internal You should not use this directly from another application |
|
161 |
* |
|
162 |
* Inline comments preceded by # are from libsodium's ref10 code. |
|
163 |
* |
|
164 |
* @param string $n |
|
165 |
* @param string $p |
|
166 |
* @return string |
|
167 |
* @throws SodiumException |
|
168 |
* @throws TypeError |
|
169 |
*/ |
|
170 |
public static function crypto_scalarmult_curve25519_ref10($n, $p) |
|
171 |
{ |
|
172 |
# for (i = 0;i < 32;++i) e[i] = n[i]; |
|
173 |
$e = '' . $n; |
|
174 |
# e[0] &= 248; |
|
175 |
$e[0] = self::intToChr( |
|
176 |
self::chrToInt($e[0]) & 248 |
|
177 |
); |
|
178 |
# e[31] &= 127; |
|
179 |
# e[31] |= 64; |
|
180 |
$e[31] = self::intToChr( |
|
181 |
(self::chrToInt($e[31]) & 127) | 64 |
|
182 |
); |
|
183 |
# fe_frombytes(x1,p); |
|
184 |
$x1 = self::fe_frombytes($p); |
|
185 |
# fe_1(x2); |
|
186 |
$x2 = self::fe_1(); |
|
187 |
# fe_0(z2); |
|
188 |
$z2 = self::fe_0(); |
|
189 |
# fe_copy(x3,x1); |
|
190 |
$x3 = self::fe_copy($x1); |
|
191 |
# fe_1(z3); |
|
192 |
$z3 = self::fe_1(); |
|
193 |
|
|
194 |
# swap = 0; |
|
195 |
/** @var int $swap */ |
|
196 |
$swap = 0; |
|
197 |
|
|
198 |
# for (pos = 254;pos >= 0;--pos) { |
|
199 |
for ($pos = 254; $pos >= 0; --$pos) { |
|
200 |
# b = e[pos / 8] >> (pos & 7); |
|
201 |
/** @var int $b */ |
|
202 |
$b = self::chrToInt( |
|
203 |
$e[(int) floor($pos / 8)] |
|
204 |
) >> ($pos & 7); |
|
205 |
# b &= 1; |
|
206 |
$b &= 1; |
|
207 |
|
|
208 |
# swap ^= b; |
|
209 |
$swap ^= $b; |
|
210 |
|
|
211 |
# fe_cswap(x2,x3,swap); |
|
212 |
self::fe_cswap($x2, $x3, $swap); |
|
213 |
|
|
214 |
# fe_cswap(z2,z3,swap); |
|
215 |
self::fe_cswap($z2, $z3, $swap); |
|
216 |
|
|
217 |
# swap = b; |
|
218 |
/** @var int $swap */ |
|
219 |
$swap = $b; |
|
220 |
|
|
221 |
# fe_sub(tmp0,x3,z3); |
|
222 |
$tmp0 = self::fe_sub($x3, $z3); |
|
223 |
|
|
224 |
# fe_sub(tmp1,x2,z2); |
|
225 |
$tmp1 = self::fe_sub($x2, $z2); |
|
226 |
|
|
227 |
# fe_add(x2,x2,z2); |
|
228 |
$x2 = self::fe_add($x2, $z2); |
|
229 |
|
|
230 |
# fe_add(z2,x3,z3); |
|
231 |
$z2 = self::fe_add($x3, $z3); |
|
232 |
|
|
233 |
# fe_mul(z3,tmp0,x2); |
|
234 |
$z3 = self::fe_mul($tmp0, $x2); |
|
235 |
|
|
236 |
# fe_mul(z2,z2,tmp1); |
|
237 |
$z2 = self::fe_mul($z2, $tmp1); |
|
238 |
|
|
239 |
# fe_sq(tmp0,tmp1); |
|
240 |
$tmp0 = self::fe_sq($tmp1); |
|
241 |
|
|
242 |
# fe_sq(tmp1,x2); |
|
243 |
$tmp1 = self::fe_sq($x2); |
|
244 |
|
|
245 |
# fe_add(x3,z3,z2); |
|
246 |
$x3 = self::fe_add($z3, $z2); |
|
247 |
|
|
248 |
# fe_sub(z2,z3,z2); |
|
249 |
$z2 = self::fe_sub($z3, $z2); |
|
250 |
|
|
251 |
# fe_mul(x2,tmp1,tmp0); |
|
252 |
$x2 = self::fe_mul($tmp1, $tmp0); |
|
253 |
|
|
254 |
# fe_sub(tmp1,tmp1,tmp0); |
|
255 |
$tmp1 = self::fe_sub($tmp1, $tmp0); |
|
256 |
|
|
257 |
# fe_sq(z2,z2); |
|
258 |
$z2 = self::fe_sq($z2); |
|
259 |
|
|
260 |
# fe_mul121666(z3,tmp1); |
|
261 |
$z3 = self::fe_mul121666($tmp1); |
|
262 |
|
|
263 |
# fe_sq(x3,x3); |
|
264 |
$x3 = self::fe_sq($x3); |
|
265 |
|
|
266 |
# fe_add(tmp0,tmp0,z3); |
|
267 |
$tmp0 = self::fe_add($tmp0, $z3); |
|
268 |
|
|
269 |
# fe_mul(z3,x1,z2); |
|
270 |
$z3 = self::fe_mul($x1, $z2); |
|
271 |
|
|
272 |
# fe_mul(z2,tmp1,tmp0); |
|
273 |
$z2 = self::fe_mul($tmp1, $tmp0); |
|
274 |
} |
|
275 |
|
|
276 |
# fe_cswap(x2,x3,swap); |
|
277 |
self::fe_cswap($x2, $x3, $swap); |
|
278 |
|
|
279 |
# fe_cswap(z2,z3,swap); |
|
280 |
self::fe_cswap($z2, $z3, $swap); |
|
281 |
|
|
282 |
# fe_invert(z2,z2); |
|
283 |
$z2 = self::fe_invert($z2); |
|
284 |
|
|
285 |
# fe_mul(x2,x2,z2); |
|
286 |
$x2 = self::fe_mul($x2, $z2); |
|
287 |
# fe_tobytes(q,x2); |
|
288 |
return (string) self::fe_tobytes($x2); |
|
289 |
} |
|
290 |
|
|
291 |
/** |
|
292 |
* @internal You should not use this directly from another application |
|
293 |
* |
|
294 |
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY |
|
295 |
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ |
|
296 |
* @return ParagonIE_Sodium_Core32_Curve25519_Fe |
|
297 |
* @throws SodiumException |
|
298 |
* @throws TypeError |
|
299 |
*/ |
|
300 |
public static function edwards_to_montgomery( |
|
301 |
ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY, |
|
302 |
ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ |
|
303 |
) { |
|
304 |
$tempX = self::fe_add($edwardsZ, $edwardsY); |
|
305 |
$tempZ = self::fe_sub($edwardsZ, $edwardsY); |
|
306 |
$tempZ = self::fe_invert($tempZ); |
|
307 |
return self::fe_mul($tempX, $tempZ); |
|
308 |
} |
|
309 |
|
|
310 |
/** |
|
311 |
* @internal You should not use this directly from another application |
|
312 |
* |
|
313 |
* @param string $n |
|
314 |
* @return string |
|
315 |
* @throws SodiumException |
|
316 |
* @throws TypeError |
|
317 |
*/ |
|
318 |
public static function crypto_scalarmult_curve25519_ref10_base($n) |
|
319 |
{ |
|
320 |
# for (i = 0;i < 32;++i) e[i] = n[i]; |
|
321 |
$e = '' . $n; |
|
322 |
|
|
323 |
# e[0] &= 248; |
|
324 |
$e[0] = self::intToChr( |
|
325 |
self::chrToInt($e[0]) & 248 |
|
326 |
); |
|
327 |
|
|
328 |
# e[31] &= 127; |
|
329 |
# e[31] |= 64; |
|
330 |
$e[31] = self::intToChr( |
|
331 |
(self::chrToInt($e[31]) & 127) | 64 |
|
332 |
); |
|
333 |
|
|
334 |
$A = self::ge_scalarmult_base($e); |
|
335 |
if ( |
|
336 |
!($A->Y instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) |
|
337 |
|| |
|
338 |
!($A->Z instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) |
|
339 |
) { |
|
340 |
throw new TypeError('Null points encountered'); |
|
341 |
} |
|
342 |
$pk = self::edwards_to_montgomery($A->Y, $A->Z); |
|
343 |
return self::fe_tobytes($pk); |
|
344 |
} |
|
345 |
} |