|
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 } |
|
154 /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */ |
|
155 return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h); |
|
156 } |
|
157 |
|
158 /** |
|
159 * @internal You should not use this directly from another application |
|
160 * |
|
161 * Inline comments preceded by # are from libsodium's ref10 code. |
|
162 * |
|
163 * @param string $n |
|
164 * @param string $p |
|
165 * @return string |
|
166 * @throws SodiumException |
|
167 * @throws TypeError |
|
168 */ |
|
169 public static function crypto_scalarmult_curve25519_ref10($n, $p) |
|
170 { |
|
171 # for (i = 0;i < 32;++i) e[i] = n[i]; |
|
172 $e = '' . $n; |
|
173 # e[0] &= 248; |
|
174 $e[0] = self::intToChr( |
|
175 self::chrToInt($e[0]) & 248 |
|
176 ); |
|
177 # e[31] &= 127; |
|
178 # e[31] |= 64; |
|
179 $e[31] = self::intToChr( |
|
180 (self::chrToInt($e[31]) & 127) | 64 |
|
181 ); |
|
182 # fe_frombytes(x1,p); |
|
183 $x1 = self::fe_frombytes($p); |
|
184 # fe_1(x2); |
|
185 $x2 = self::fe_1(); |
|
186 # fe_0(z2); |
|
187 $z2 = self::fe_0(); |
|
188 # fe_copy(x3,x1); |
|
189 $x3 = self::fe_copy($x1); |
|
190 # fe_1(z3); |
|
191 $z3 = self::fe_1(); |
|
192 |
|
193 # swap = 0; |
|
194 /** @var int $swap */ |
|
195 $swap = 0; |
|
196 |
|
197 # for (pos = 254;pos >= 0;--pos) { |
|
198 for ($pos = 254; $pos >= 0; --$pos) { |
|
199 # b = e[pos / 8] >> (pos & 7); |
|
200 /** @var int $b */ |
|
201 $b = self::chrToInt( |
|
202 $e[(int) floor($pos / 8)] |
|
203 ) >> ($pos & 7); |
|
204 # b &= 1; |
|
205 $b &= 1; |
|
206 |
|
207 # swap ^= b; |
|
208 $swap ^= $b; |
|
209 |
|
210 # fe_cswap(x2,x3,swap); |
|
211 self::fe_cswap($x2, $x3, $swap); |
|
212 |
|
213 # fe_cswap(z2,z3,swap); |
|
214 self::fe_cswap($z2, $z3, $swap); |
|
215 |
|
216 # swap = b; |
|
217 /** @var int $swap */ |
|
218 $swap = $b; |
|
219 |
|
220 # fe_sub(tmp0,x3,z3); |
|
221 $tmp0 = self::fe_sub($x3, $z3); |
|
222 |
|
223 # fe_sub(tmp1,x2,z2); |
|
224 $tmp1 = self::fe_sub($x2, $z2); |
|
225 |
|
226 # fe_add(x2,x2,z2); |
|
227 $x2 = self::fe_add($x2, $z2); |
|
228 |
|
229 # fe_add(z2,x3,z3); |
|
230 $z2 = self::fe_add($x3, $z3); |
|
231 |
|
232 # fe_mul(z3,tmp0,x2); |
|
233 $z3 = self::fe_mul($tmp0, $x2); |
|
234 |
|
235 # fe_mul(z2,z2,tmp1); |
|
236 $z2 = self::fe_mul($z2, $tmp1); |
|
237 |
|
238 # fe_sq(tmp0,tmp1); |
|
239 $tmp0 = self::fe_sq($tmp1); |
|
240 |
|
241 # fe_sq(tmp1,x2); |
|
242 $tmp1 = self::fe_sq($x2); |
|
243 |
|
244 # fe_add(x3,z3,z2); |
|
245 $x3 = self::fe_add($z3, $z2); |
|
246 |
|
247 # fe_sub(z2,z3,z2); |
|
248 $z2 = self::fe_sub($z3, $z2); |
|
249 |
|
250 # fe_mul(x2,tmp1,tmp0); |
|
251 $x2 = self::fe_mul($tmp1, $tmp0); |
|
252 |
|
253 # fe_sub(tmp1,tmp1,tmp0); |
|
254 $tmp1 = self::fe_sub($tmp1, $tmp0); |
|
255 |
|
256 # fe_sq(z2,z2); |
|
257 $z2 = self::fe_sq($z2); |
|
258 |
|
259 # fe_mul121666(z3,tmp1); |
|
260 $z3 = self::fe_mul121666($tmp1); |
|
261 |
|
262 # fe_sq(x3,x3); |
|
263 $x3 = self::fe_sq($x3); |
|
264 |
|
265 # fe_add(tmp0,tmp0,z3); |
|
266 $tmp0 = self::fe_add($tmp0, $z3); |
|
267 |
|
268 # fe_mul(z3,x1,z2); |
|
269 $z3 = self::fe_mul($x1, $z2); |
|
270 |
|
271 # fe_mul(z2,tmp1,tmp0); |
|
272 $z2 = self::fe_mul($tmp1, $tmp0); |
|
273 } |
|
274 |
|
275 # fe_cswap(x2,x3,swap); |
|
276 self::fe_cswap($x2, $x3, $swap); |
|
277 |
|
278 # fe_cswap(z2,z3,swap); |
|
279 self::fe_cswap($z2, $z3, $swap); |
|
280 |
|
281 # fe_invert(z2,z2); |
|
282 $z2 = self::fe_invert($z2); |
|
283 |
|
284 # fe_mul(x2,x2,z2); |
|
285 $x2 = self::fe_mul($x2, $z2); |
|
286 # fe_tobytes(q,x2); |
|
287 return (string) self::fe_tobytes($x2); |
|
288 } |
|
289 |
|
290 /** |
|
291 * @internal You should not use this directly from another application |
|
292 * |
|
293 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY |
|
294 * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ |
|
295 * @return ParagonIE_Sodium_Core32_Curve25519_Fe |
|
296 * @throws SodiumException |
|
297 * @throws TypeError |
|
298 */ |
|
299 public static function edwards_to_montgomery( |
|
300 ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY, |
|
301 ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ |
|
302 ) { |
|
303 $tempX = self::fe_add($edwardsZ, $edwardsY); |
|
304 $tempZ = self::fe_sub($edwardsZ, $edwardsY); |
|
305 $tempZ = self::fe_invert($tempZ); |
|
306 return self::fe_mul($tempX, $tempZ); |
|
307 } |
|
308 |
|
309 /** |
|
310 * @internal You should not use this directly from another application |
|
311 * |
|
312 * @param string $n |
|
313 * @return string |
|
314 * @throws SodiumException |
|
315 * @throws TypeError |
|
316 */ |
|
317 public static function crypto_scalarmult_curve25519_ref10_base($n) |
|
318 { |
|
319 # for (i = 0;i < 32;++i) e[i] = n[i]; |
|
320 $e = '' . $n; |
|
321 |
|
322 # e[0] &= 248; |
|
323 $e[0] = self::intToChr( |
|
324 self::chrToInt($e[0]) & 248 |
|
325 ); |
|
326 |
|
327 # e[31] &= 127; |
|
328 # e[31] |= 64; |
|
329 $e[31] = self::intToChr( |
|
330 (self::chrToInt($e[31]) & 127) | 64 |
|
331 ); |
|
332 |
|
333 $A = self::ge_scalarmult_base($e); |
|
334 if ( |
|
335 !($A->Y instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) |
|
336 || |
|
337 !($A->Z instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) |
|
338 ) { |
|
339 throw new TypeError('Null points encountered'); |
|
340 } |
|
341 $pk = self::edwards_to_montgomery($A->Y, $A->Z); |
|
342 return self::fe_tobytes($pk); |
|
343 } |
|
344 } |