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