run:R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
160.83 KB
2026-03-11 16:18:52
R W Run
53.68 KB
2026-03-11 16:18:52
R W Run
53.83 KB
2026-03-11 16:18:52
R W Run
53.53 KB
2026-03-11 16:18:52
R W Run
158 By
2026-03-11 16:18:52
R W Run
error_log
📄Crypto.php
1<?php
2
3if (class_exists('ParagonIE_Sodium_Crypto', false)) {
4 return;
5}
6
7/**
8 * Class ParagonIE_Sodium_Crypto
9 *
10 * ATTENTION!
11 *
12 * If you are using this library, you should be using
13 * ParagonIE_Sodium_Compat in your code, not this class.
14 */
15abstract class ParagonIE_Sodium_Crypto
16{
17 const aead_chacha20poly1305_KEYBYTES = 32;
18 const aead_chacha20poly1305_NSECBYTES = 0;
19 const aead_chacha20poly1305_NPUBBYTES = 8;
20 const aead_chacha20poly1305_ABYTES = 16;
21
22 const aead_chacha20poly1305_IETF_KEYBYTES = 32;
23 const aead_chacha20poly1305_IETF_NSECBYTES = 0;
24 const aead_chacha20poly1305_IETF_NPUBBYTES = 12;
25 const aead_chacha20poly1305_IETF_ABYTES = 16;
26
27 const aead_xchacha20poly1305_IETF_KEYBYTES = 32;
28 const aead_xchacha20poly1305_IETF_NSECBYTES = 0;
29 const aead_xchacha20poly1305_IETF_NPUBBYTES = 24;
30 const aead_xchacha20poly1305_IETF_ABYTES = 16;
31
32 const box_curve25519xsalsa20poly1305_SEEDBYTES = 32;
33 const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32;
34 const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32;
35 const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32;
36 const box_curve25519xsalsa20poly1305_NONCEBYTES = 24;
37 const box_curve25519xsalsa20poly1305_MACBYTES = 16;
38 const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16;
39 const box_curve25519xsalsa20poly1305_ZEROBYTES = 32;
40
41 const onetimeauth_poly1305_BYTES = 16;
42 const onetimeauth_poly1305_KEYBYTES = 32;
43
44 const secretbox_xsalsa20poly1305_KEYBYTES = 32;
45 const secretbox_xsalsa20poly1305_NONCEBYTES = 24;
46 const secretbox_xsalsa20poly1305_MACBYTES = 16;
47 const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16;
48 const secretbox_xsalsa20poly1305_ZEROBYTES = 32;
49
50 const secretbox_xchacha20poly1305_KEYBYTES = 32;
51 const secretbox_xchacha20poly1305_NONCEBYTES = 24;
52 const secretbox_xchacha20poly1305_MACBYTES = 16;
53 const secretbox_xchacha20poly1305_BOXZEROBYTES = 16;
54 const secretbox_xchacha20poly1305_ZEROBYTES = 32;
55
56 const stream_salsa20_KEYBYTES = 32;
57
58 /**
59 * AEAD Decryption with ChaCha20-Poly1305
60 *
61 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
62 *
63 * @param string $message
64 * @param string $ad
65 * @param string $nonce
66 * @param string $key
67 * @return string
68 * @throws SodiumException
69 * @throws TypeError
70 */
71 public static function aead_chacha20poly1305_decrypt(
72 $message = '',
73 $ad = '',
74 $nonce = '',
75 $key = ''
76 ) {
77 /** @var int $len - Length of message (ciphertext + MAC) */
78 $len = ParagonIE_Sodium_Core_Util::strlen($message);
79
80 /** @var int $clen - Length of ciphertext */
81 $clen = $len - self::aead_chacha20poly1305_ABYTES;
82
83 /** @var int $adlen - Length of associated data */
84 $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);
85
86 /** @var string $mac - Message authentication code */
87 $mac = ParagonIE_Sodium_Core_Util::substr(
88 $message,
89 $clen,
90 self::aead_chacha20poly1305_ABYTES
91 );
92
93 /** @var string $ciphertext - The encrypted message (sans MAC) */
94 $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 0, $clen);
95
96 /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
97 $block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
98 32,
99 $nonce,
100 $key
101 );
102
103 /* Recalculate the Poly1305 authentication tag (MAC): */
104 $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
105 try {
106 ParagonIE_Sodium_Compat::memzero($block0);
107 } catch (SodiumException $ex) {
108 $block0 = null;
109 }
110 $state->update($ad);
111 $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
112 $state->update($ciphertext);
113 $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen));
114 $computed_mac = $state->finish();
115
116 /* Compare the given MAC with the recalculated MAC: */
117 if (!ParagonIE_Sodium_Core_Util::verify_16($computed_mac, $mac)) {
118 throw new SodiumException('Invalid MAC');
119 }
120
121 // Here, we know that the MAC is valid, so we decrypt and return the plaintext
122 return ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
123 $ciphertext,
124 $nonce,
125 $key,
126 ParagonIE_Sodium_Core_Util::store64_le(1)
127 );
128 }
129
130 /**
131 * AEAD Encryption with ChaCha20-Poly1305
132 *
133 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
134 *
135 * @param string $message
136 * @param string $ad
137 * @param string $nonce
138 * @param string $key
139 * @return string
140 * @throws SodiumException
141 * @throws TypeError
142 */
143 public static function aead_chacha20poly1305_encrypt(
144 $message = '',
145 $ad = '',
146 $nonce = '',
147 $key = ''
148 ) {
149 /** @var int $len - Length of the plaintext message */
150 $len = ParagonIE_Sodium_Core_Util::strlen($message);
151
152 /** @var int $adlen - Length of the associated data */
153 $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);
154
155 /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
156 $block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
157 32,
158 $nonce,
159 $key
160 );
161 $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
162 try {
163 ParagonIE_Sodium_Compat::memzero($block0);
164 } catch (SodiumException $ex) {
165 $block0 = null;
166 }
167
168 /** @var string $ciphertext - Raw encrypted data */
169 $ciphertext = ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
170 $message,
171 $nonce,
172 $key,
173 ParagonIE_Sodium_Core_Util::store64_le(1)
174 );
175
176 $state->update($ad);
177 $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
178 $state->update($ciphertext);
179 $state->update(ParagonIE_Sodium_Core_Util::store64_le($len));
180 return $ciphertext . $state->finish();
181 }
182
183 /**
184 * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
185 *
186 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
187 *
188 * @param string $message
189 * @param string $ad
190 * @param string $nonce
191 * @param string $key
192 * @return string
193 * @throws SodiumException
194 * @throws TypeError
195 */
196 public static function aead_chacha20poly1305_ietf_decrypt(
197 $message = '',
198 $ad = '',
199 $nonce = '',
200 $key = ''
201 ) {
202 /** @var int $adlen - Length of associated data */
203 $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);
204
205 /** @var int $len - Length of message (ciphertext + MAC) */
206 $len = ParagonIE_Sodium_Core_Util::strlen($message);
207
208 /** @var int $clen - Length of ciphertext */
209 $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES;
210
211 /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
212 $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream(
213 32,
214 $nonce,
215 $key
216 );
217
218 /** @var string $mac - Message authentication code */
219 $mac = ParagonIE_Sodium_Core_Util::substr(
220 $message,
221 $len - self::aead_chacha20poly1305_IETF_ABYTES,
222 self::aead_chacha20poly1305_IETF_ABYTES
223 );
224
225 /** @var string $ciphertext - The encrypted message (sans MAC) */
226 $ciphertext = ParagonIE_Sodium_Core_Util::substr(
227 $message,
228 0,
229 $len - self::aead_chacha20poly1305_IETF_ABYTES
230 );
231
232 /* Recalculate the Poly1305 authentication tag (MAC): */
233 $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
234 try {
235 ParagonIE_Sodium_Compat::memzero($block0);
236 } catch (SodiumException $ex) {
237 $block0 = null;
238 }
239 $state->update($ad);
240 $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
241 $state->update($ciphertext);
242 $state->update(str_repeat("\x00", (0x10 - $clen) & 0xf));
243 $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
244 $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen));
245 $computed_mac = $state->finish();
246
247 /* Compare the given MAC with the recalculated MAC: */
248 if (!ParagonIE_Sodium_Core_Util::verify_16($computed_mac, $mac)) {
249 throw new SodiumException('Invalid MAC');
250 }
251
252 // Here, we know that the MAC is valid, so we decrypt and return the plaintext
253 return ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
254 $ciphertext,
255 $nonce,
256 $key,
257 ParagonIE_Sodium_Core_Util::store64_le(1)
258 );
259 }
260
261 /**
262 * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
263 *
264 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
265 *
266 * @param string $message
267 * @param string $ad
268 * @param string $nonce
269 * @param string $key
270 * @return string
271 * @throws SodiumException
272 * @throws TypeError
273 */
274 public static function aead_chacha20poly1305_ietf_encrypt(
275 $message = '',
276 $ad = '',
277 $nonce = '',
278 $key = ''
279 ) {
280 /** @var int $len - Length of the plaintext message */
281 $len = ParagonIE_Sodium_Core_Util::strlen($message);
282
283 /** @var int $adlen - Length of the associated data */
284 $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);
285
286 /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
287 $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream(
288 32,
289 $nonce,
290 $key
291 );
292 $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
293 try {
294 ParagonIE_Sodium_Compat::memzero($block0);
295 } catch (SodiumException $ex) {
296 $block0 = null;
297 }
298
299 /** @var string $ciphertext - Raw encrypted data */
300 $ciphertext = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
301 $message,
302 $nonce,
303 $key,
304 ParagonIE_Sodium_Core_Util::store64_le(1)
305 );
306
307 $state->update($ad);
308 $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
309 $state->update($ciphertext);
310 $state->update(str_repeat("\x00", ((0x10 - $len) & 0xf)));
311 $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
312 $state->update(ParagonIE_Sodium_Core_Util::store64_le($len));
313 return $ciphertext . $state->finish();
314 }
315
316 /**
317 * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
318 *
319 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
320 *
321 * @param string $message
322 * @param string $ad
323 * @param string $nonce
324 * @param string $key
325 * @return string
326 * @throws SodiumException
327 * @throws TypeError
328 */
329 public static function aead_xchacha20poly1305_ietf_decrypt(
330 $message = '',
331 $ad = '',
332 $nonce = '',
333 $key = ''
334 ) {
335 $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
336 ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
337 $key
338 );
339 $nonceLast = "\x00\x00\x00\x00" .
340 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
341
342 return self::aead_chacha20poly1305_ietf_decrypt($message, $ad, $nonceLast, $subkey);
343 }
344
345 /**
346 * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
347 *
348 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
349 *
350 * @param string $message
351 * @param string $ad
352 * @param string $nonce
353 * @param string $key
354 * @return string
355 * @throws SodiumException
356 * @throws TypeError
357 */
358 public static function aead_xchacha20poly1305_ietf_encrypt(
359 $message = '',
360 $ad = '',
361 $nonce = '',
362 $key = ''
363 ) {
364 $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
365 ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
366 $key
367 );
368 $nonceLast = "\x00\x00\x00\x00" .
369 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
370
371 return self::aead_chacha20poly1305_ietf_encrypt($message, $ad, $nonceLast, $subkey);
372 }
373
374 /**
375 * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
376 *
377 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
378 *
379 * @param string $message
380 * @param string $key
381 * @return string
382 * @throws TypeError
383 */
384 public static function auth($message, $key)
385 {
386 return ParagonIE_Sodium_Core_Util::substr(
387 hash_hmac('sha512', $message, $key, true),
388 0,
389 32
390 );
391 }
392
393 /**
394 * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
395 *
396 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
397 *
398 * @param string $mac
399 * @param string $message
400 * @param string $key
401 * @return bool
402 * @throws SodiumException
403 * @throws TypeError
404 */
405 public static function auth_verify($mac, $message, $key)
406 {
407 return ParagonIE_Sodium_Core_Util::hashEquals(
408 $mac,
409 self::auth($message, $key)
410 );
411 }
412
413 /**
414 * X25519 key exchange followed by XSalsa20Poly1305 symmetric encryption
415 *
416 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
417 *
418 * @param string $plaintext
419 * @param string $nonce
420 * @param string $keypair
421 * @return string
422 * @throws SodiumException
423 * @throws TypeError
424 */
425 public static function box($plaintext, $nonce, $keypair)
426 {
427 $c = self::secretbox(
428 $plaintext,
429 $nonce,
430 self::box_beforenm(
431 self::box_secretkey($keypair),
432 self::box_publickey($keypair)
433 )
434 );
435 return $c;
436 }
437
438 /**
439 * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair.
440 *
441 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
442 *
443 * @param string $message
444 * @param string $publicKey
445 * @return string
446 * @throws SodiumException
447 * @throws TypeError
448 */
449 public static function box_seal($message, $publicKey)
450 {
451 /** @var string $ephemeralKeypair */
452 $ephemeralKeypair = self::box_keypair();
453
454 /** @var string $ephemeralSK */
455 $ephemeralSK = self::box_secretkey($ephemeralKeypair);
456
457 /** @var string $ephemeralPK */
458 $ephemeralPK = self::box_publickey($ephemeralKeypair);
459
460 /** @var string $nonce */
461 $nonce = self::generichash(
462 $ephemeralPK . $publicKey,
463 '',
464 24
465 );
466
467 /** @var string $keypair - The combined keypair used in crypto_box() */
468 $keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);
469
470 /** @var string $ciphertext Ciphertext + MAC from crypto_box */
471 $ciphertext = self::box($message, $nonce, $keypair);
472 try {
473 ParagonIE_Sodium_Compat::memzero($ephemeralKeypair);
474 ParagonIE_Sodium_Compat::memzero($ephemeralSK);
475 ParagonIE_Sodium_Compat::memzero($nonce);
476 } catch (SodiumException $ex) {
477 $ephemeralKeypair = null;
478 $ephemeralSK = null;
479 $nonce = null;
480 }
481 return $ephemeralPK . $ciphertext;
482 }
483
484 /**
485 * Opens a message encrypted via box_seal().
486 *
487 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
488 *
489 * @param string $message
490 * @param string $keypair
491 * @return string
492 * @throws SodiumException
493 * @throws TypeError
494 */
495 public static function box_seal_open($message, $keypair)
496 {
497 /** @var string $ephemeralPK */
498 $ephemeralPK = ParagonIE_Sodium_Core_Util::substr($message, 0, 32);
499
500 /** @var string $ciphertext (ciphertext + MAC) */
501 $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 32);
502
503 /** @var string $secretKey */
504 $secretKey = self::box_secretkey($keypair);
505
506 /** @var string $publicKey */
507 $publicKey = self::box_publickey($keypair);
508
509 /** @var string $nonce */
510 $nonce = self::generichash(
511 $ephemeralPK . $publicKey,
512 '',
513 24
514 );
515
516 /** @var string $keypair */
517 $keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);
518
519 /** @var string $m */
520 $m = self::box_open($ciphertext, $nonce, $keypair);
521 try {
522 ParagonIE_Sodium_Compat::memzero($secretKey);
523 ParagonIE_Sodium_Compat::memzero($ephemeralPK);
524 ParagonIE_Sodium_Compat::memzero($nonce);
525 } catch (SodiumException $ex) {
526 $secretKey = null;
527 $ephemeralPK = null;
528 $nonce = null;
529 }
530 return $m;
531 }
532
533 /**
534 * Used by crypto_box() to get the crypto_secretbox() key.
535 *
536 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
537 *
538 * @param string $sk
539 * @param string $pk
540 * @return string
541 * @throws SodiumException
542 * @throws TypeError
543 */
544 public static function box_beforenm($sk, $pk)
545 {
546 return ParagonIE_Sodium_Core_HSalsa20::hsalsa20(
547 str_repeat("\x00", 16),
548 self::scalarmult($sk, $pk)
549 );
550 }
551
552 /**
553 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
554 *
555 * @return string
556 * @throws Exception
557 * @throws SodiumException
558 * @throws TypeError
559 */
560 public static function box_keypair()
561 {
562 $sKey = random_bytes(32);
563 $pKey = self::scalarmult_base($sKey);
564 return $sKey . $pKey;
565 }
566
567 /**
568 * @param string $seed
569 * @return string
570 * @throws SodiumException
571 * @throws TypeError
572 */
573 public static function box_seed_keypair($seed)
574 {
575 $sKey = ParagonIE_Sodium_Core_Util::substr(
576 hash('sha512', $seed, true),
577 0,
578 32
579 );
580 $pKey = self::scalarmult_base($sKey);
581 return $sKey . $pKey;
582 }
583
584 /**
585 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
586 *
587 * @param string $sKey
588 * @param string $pKey
589 * @return string
590 * @throws TypeError
591 */
592 public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey)
593 {
594 return ParagonIE_Sodium_Core_Util::substr($sKey, 0, 32) .
595 ParagonIE_Sodium_Core_Util::substr($pKey, 0, 32);
596 }
597
598 /**
599 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
600 *
601 * @param string $keypair
602 * @return string
603 * @throws RangeException
604 * @throws TypeError
605 */
606 public static function box_secretkey($keypair)
607 {
608 if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== 64) {
609 throw new RangeException(
610 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
611 );
612 }
613 return ParagonIE_Sodium_Core_Util::substr($keypair, 0, 32);
614 }
615
616 /**
617 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
618 *
619 * @param string $keypair
620 * @return string
621 * @throws RangeException
622 * @throws TypeError
623 */
624 public static function box_publickey($keypair)
625 {
626 if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
627 throw new RangeException(
628 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
629 );
630 }
631 return ParagonIE_Sodium_Core_Util::substr($keypair, 32, 32);
632 }
633
634 /**
635 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
636 *
637 * @param string $sKey
638 * @return string
639 * @throws RangeException
640 * @throws SodiumException
641 * @throws TypeError
642 */
643 public static function box_publickey_from_secretkey($sKey)
644 {
645 if (ParagonIE_Sodium_Core_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) {
646 throw new RangeException(
647 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.'
648 );
649 }
650 return self::scalarmult_base($sKey);
651 }
652
653 /**
654 * Decrypt a message encrypted with box().
655 *
656 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
657 *
658 * @param string $ciphertext
659 * @param string $nonce
660 * @param string $keypair
661 * @return string
662 * @throws SodiumException
663 * @throws TypeError
664 */
665 public static function box_open($ciphertext, $nonce, $keypair)
666 {
667 return self::secretbox_open(
668 $ciphertext,
669 $nonce,
670 self::box_beforenm(
671 self::box_secretkey($keypair),
672 self::box_publickey($keypair)
673 )
674 );
675 }
676
677 /**
678 * Calculate a BLAKE2b hash.
679 *
680 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
681 *
682 * @param string $message
683 * @param string|null $key
684 * @param int $outlen
685 * @return string
686 * @throws RangeException
687 * @throws SodiumException
688 * @throws TypeError
689 */
690 public static function generichash($message, $key = '', $outlen = 32)
691 {
692 // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
693 ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
694
695 $k = null;
696 if (!empty($key)) {
697 /** @var SplFixedArray $k */
698 $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
699 if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
700 throw new RangeException('Invalid key size');
701 }
702 }
703
704 /** @var SplFixedArray $in */
705 $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);
706
707 /** @var SplFixedArray $ctx */
708 $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outlen);
709 ParagonIE_Sodium_Core_BLAKE2b::update($ctx, $in, $in->count());
710
711 /** @var SplFixedArray $out */
712 $out = new SplFixedArray($outlen);
713 $out = ParagonIE_Sodium_Core_BLAKE2b::finish($ctx, $out);
714
715 /** @var array<int, int> */
716 $outArray = $out->toArray();
717 return ParagonIE_Sodium_Core_Util::intArrayToString($outArray);
718 }
719
720 /**
721 * Finalize a BLAKE2b hashing context, returning the hash.
722 *
723 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
724 *
725 * @param string $ctx
726 * @param int $outlen
727 * @return string
728 * @throws SodiumException
729 * @throws TypeError
730 */
731 public static function generichash_final($ctx, $outlen = 32)
732 {
733 if (!is_string($ctx)) {
734 throw new TypeError('Context must be a string');
735 }
736 $out = new SplFixedArray($outlen);
737
738 /** @var SplFixedArray $context */
739 $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
740
741 /** @var SplFixedArray $out */
742 $out = ParagonIE_Sodium_Core_BLAKE2b::finish($context, $out);
743
744 /** @var array<int, int> */
745 $outArray = $out->toArray();
746 return ParagonIE_Sodium_Core_Util::intArrayToString($outArray);
747 }
748
749 /**
750 * Initialize a hashing context for BLAKE2b.
751 *
752 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
753 *
754 * @param string $key
755 * @param int $outputLength
756 * @return string
757 * @throws RangeException
758 * @throws SodiumException
759 * @throws TypeError
760 */
761 public static function generichash_init($key = '', $outputLength = 32)
762 {
763 // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
764 ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
765
766 $k = null;
767 if (!empty($key)) {
768 $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
769 if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
770 throw new RangeException('Invalid key size');
771 }
772 }
773
774 /** @var SplFixedArray $ctx */
775 $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength);
776
777 return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
778 }
779
780 /**
781 * Initialize a hashing context for BLAKE2b.
782 *
783 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
784 *
785 * @param string $key
786 * @param int $outputLength
787 * @param string $salt
788 * @param string $personal
789 * @return string
790 * @throws RangeException
791 * @throws SodiumException
792 * @throws TypeError
793 */
794 public static function generichash_init_salt_personal(
795 $key = '',
796 $outputLength = 32,
797 $salt = '',
798 $personal = ''
799 ) {
800 // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
801 ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
802
803 $k = null;
804 if (!empty($key)) {
805 $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
806 if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
807 throw new RangeException('Invalid key size');
808 }
809 }
810 if (!empty($salt)) {
811 $s = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt);
812 } else {
813 $s = null;
814 }
815 if (!empty($salt)) {
816 $p = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal);
817 } else {
818 $p = null;
819 }
820
821 /** @var SplFixedArray $ctx */
822 $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s, $p);
823
824 return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
825 }
826
827 /**
828 * Update a hashing context for BLAKE2b with $message
829 *
830 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
831 *
832 * @param string $ctx
833 * @param string $message
834 * @return string
835 * @throws SodiumException
836 * @throws TypeError
837 */
838 public static function generichash_update($ctx, $message)
839 {
840 // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
841 ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
842
843 /** @var SplFixedArray $context */
844 $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
845
846 /** @var SplFixedArray $in */
847 $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);
848
849 ParagonIE_Sodium_Core_BLAKE2b::update($context, $in, $in->count());
850
851 return ParagonIE_Sodium_Core_BLAKE2b::contextToString($context);
852 }
853
854 /**
855 * Libsodium's crypto_kx().
856 *
857 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
858 *
859 * @param string $my_sk
860 * @param string $their_pk
861 * @param string $client_pk
862 * @param string $server_pk
863 * @return string
864 * @throws SodiumException
865 * @throws TypeError
866 */
867 public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk)
868 {
869 return ParagonIE_Sodium_Compat::crypto_generichash(
870 ParagonIE_Sodium_Compat::crypto_scalarmult($my_sk, $their_pk) .
871 $client_pk .
872 $server_pk
873 );
874 }
875
876 /**
877 * ECDH over Curve25519
878 *
879 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
880 *
881 * @param string $sKey
882 * @param string $pKey
883 * @return string
884 *
885 * @throws SodiumException
886 * @throws TypeError
887 */
888 public static function scalarmult($sKey, $pKey)
889 {
890 $q = ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey);
891 self::scalarmult_throw_if_zero($q);
892 return $q;
893 }
894
895 /**
896 * ECDH over Curve25519, using the basepoint.
897 * Used to get a secret key from a public key.
898 *
899 * @param string $secret
900 * @return string
901 *
902 * @throws SodiumException
903 * @throws TypeError
904 */
905 public static function scalarmult_base($secret)
906 {
907 $q = ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
908 self::scalarmult_throw_if_zero($q);
909 return $q;
910 }
911
912 /**
913 * This throws an Error if a zero public key was passed to the function.
914 *
915 * @param string $q
916 * @return void
917 * @throws SodiumException
918 * @throws TypeError
919 */
920 protected static function scalarmult_throw_if_zero($q)
921 {
922 $d = 0;
923 for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
924 $d |= ParagonIE_Sodium_Core_Util::chrToInt($q[$i]);
925 }
926
927 /* branch-free variant of === 0 */
928 if (-(1 & (($d - 1) >> 8))) {
929 throw new SodiumException('Zero public key is not allowed');
930 }
931 }
932
933 /**
934 * XSalsa20-Poly1305 authenticated symmetric-key encryption.
935 *
936 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
937 *
938 * @param string $plaintext
939 * @param string $nonce
940 * @param string $key
941 * @return string
942 * @throws SodiumException
943 * @throws TypeError
944 */
945 public static function secretbox($plaintext, $nonce, $key)
946 {
947 /** @var string $subkey */
948 $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
949
950 /** @var string $block0 */
951 $block0 = str_repeat("\x00", 32);
952
953 /** @var int $mlen - Length of the plaintext message */
954 $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext);
955 $mlen0 = $mlen;
956 if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
957 $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
958 }
959 $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0);
960
961 /** @var string $block0 */
962 $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
963 $block0,
964 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
965 $subkey
966 );
967
968 /** @var string $c */
969 $c = ParagonIE_Sodium_Core_Util::substr(
970 $block0,
971 self::secretbox_xsalsa20poly1305_ZEROBYTES
972 );
973 if ($mlen > $mlen0) {
974 $c .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
975 ParagonIE_Sodium_Core_Util::substr(
976 $plaintext,
977 self::secretbox_xsalsa20poly1305_ZEROBYTES
978 ),
979 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
980 1,
981 $subkey
982 );
983 }
984 $state = new ParagonIE_Sodium_Core_Poly1305_State(
985 ParagonIE_Sodium_Core_Util::substr(
986 $block0,
987 0,
988 self::onetimeauth_poly1305_KEYBYTES
989 )
990 );
991 try {
992 ParagonIE_Sodium_Compat::memzero($block0);
993 ParagonIE_Sodium_Compat::memzero($subkey);
994 } catch (SodiumException $ex) {
995 $block0 = null;
996 $subkey = null;
997 }
998
999 $state->update($c);
1000
1001 /** @var string $c - MAC || ciphertext */
1002 $c = $state->finish() . $c;
1003 unset($state);
1004
1005 return $c;
1006 }
1007
1008 /**
1009 * Decrypt a ciphertext generated via secretbox().
1010 *
1011 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1012 *
1013 * @param string $ciphertext
1014 * @param string $nonce
1015 * @param string $key
1016 * @return string
1017 * @throws SodiumException
1018 * @throws TypeError
1019 */
1020 public static function secretbox_open($ciphertext, $nonce, $key)
1021 {
1022 /** @var string $mac */
1023 $mac = ParagonIE_Sodium_Core_Util::substr(
1024 $ciphertext,
1025 0,
1026 self::secretbox_xsalsa20poly1305_MACBYTES
1027 );
1028
1029 /** @var string $c */
1030 $c = ParagonIE_Sodium_Core_Util::substr(
1031 $ciphertext,
1032 self::secretbox_xsalsa20poly1305_MACBYTES
1033 );
1034
1035 /** @var int $clen */
1036 $clen = ParagonIE_Sodium_Core_Util::strlen($c);
1037
1038 /** @var string $subkey */
1039 $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
1040
1041 /** @var string $block0 */
1042 $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20(
1043 64,
1044 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
1045 $subkey
1046 );
1047 $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify(
1048 $mac,
1049 $c,
1050 ParagonIE_Sodium_Core_Util::substr($block0, 0, 32)
1051 );
1052 if (!$verified) {
1053 try {
1054 ParagonIE_Sodium_Compat::memzero($subkey);
1055 } catch (SodiumException $ex) {
1056 $subkey = null;
1057 }
1058 throw new SodiumException('Invalid MAC');
1059 }
1060
1061 /** @var string $m - Decrypted message */
1062 $m = ParagonIE_Sodium_Core_Util::xorStrings(
1063 ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES),
1064 ParagonIE_Sodium_Core_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES)
1065 );
1066 if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
1067 // We had more than 1 block, so let's continue to decrypt the rest.
1068 $m .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
1069 ParagonIE_Sodium_Core_Util::substr(
1070 $c,
1071 self::secretbox_xsalsa20poly1305_ZEROBYTES
1072 ),
1073 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
1074 1,
1075 (string) $subkey
1076 );
1077 }
1078 return $m;
1079 }
1080
1081 /**
1082 * XChaCha20-Poly1305 authenticated symmetric-key encryption.
1083 *
1084 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1085 *
1086 * @param string $plaintext
1087 * @param string $nonce
1088 * @param string $key
1089 * @return string
1090 * @throws SodiumException
1091 * @throws TypeError
1092 */
1093 public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key)
1094 {
1095 /** @var string $subkey */
1096 $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
1097 ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
1098 $key
1099 );
1100 $nonceLast = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
1101
1102 /** @var string $block0 */
1103 $block0 = str_repeat("\x00", 32);
1104
1105 /** @var int $mlen - Length of the plaintext message */
1106 $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext);
1107 $mlen0 = $mlen;
1108 if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) {
1109 $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES;
1110 }
1111 $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0);
1112
1113 /** @var string $block0 */
1114 $block0 = ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
1115 $block0,
1116 $nonceLast,
1117 $subkey
1118 );
1119
1120 /** @var string $c */
1121 $c = ParagonIE_Sodium_Core_Util::substr(
1122 $block0,
1123 self::secretbox_xchacha20poly1305_ZEROBYTES
1124 );
1125 if ($mlen > $mlen0) {
1126 $c .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
1127 ParagonIE_Sodium_Core_Util::substr(
1128 $plaintext,
1129 self::secretbox_xchacha20poly1305_ZEROBYTES
1130 ),
1131 $nonceLast,
1132 $subkey,
1133 ParagonIE_Sodium_Core_Util::store64_le(1)
1134 );
1135 }
1136 $state = new ParagonIE_Sodium_Core_Poly1305_State(
1137 ParagonIE_Sodium_Core_Util::substr(
1138 $block0,
1139 0,
1140 self::onetimeauth_poly1305_KEYBYTES
1141 )
1142 );
1143 try {
1144 ParagonIE_Sodium_Compat::memzero($block0);
1145 ParagonIE_Sodium_Compat::memzero($subkey);
1146 } catch (SodiumException $ex) {
1147 $block0 = null;
1148 $subkey = null;
1149 }
1150
1151 $state->update($c);
1152
1153 /** @var string $c - MAC || ciphertext */
1154 $c = $state->finish() . $c;
1155 unset($state);
1156
1157 return $c;
1158 }
1159
1160 /**
1161 * Decrypt a ciphertext generated via secretbox_xchacha20poly1305().
1162 *
1163 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1164 *
1165 * @param string $ciphertext
1166 * @param string $nonce
1167 * @param string $key
1168 * @return string
1169 * @throws SodiumException
1170 * @throws TypeError
1171 */
1172 public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key)
1173 {
1174 /** @var string $mac */
1175 $mac = ParagonIE_Sodium_Core_Util::substr(
1176 $ciphertext,
1177 0,
1178 self::secretbox_xchacha20poly1305_MACBYTES
1179 );
1180
1181 /** @var string $c */
1182 $c = ParagonIE_Sodium_Core_Util::substr(
1183 $ciphertext,
1184 self::secretbox_xchacha20poly1305_MACBYTES
1185 );
1186
1187 /** @var int $clen */
1188 $clen = ParagonIE_Sodium_Core_Util::strlen($c);
1189
1190 /** @var string $subkey */
1191 $subkey = ParagonIE_Sodium_Core_HChaCha20::hchacha20(
1192 ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
1193 $key
1194 );
1195
1196 /** @var string $block0 */
1197 $block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
1198 64,
1199 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
1200 $subkey
1201 );
1202 $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify(
1203 $mac,
1204 $c,
1205 ParagonIE_Sodium_Core_Util::substr($block0, 0, 32)
1206 );
1207
1208 if (!$verified) {
1209 try {
1210 ParagonIE_Sodium_Compat::memzero($subkey);
1211 } catch (SodiumException $ex) {
1212 $subkey = null;
1213 }
1214 throw new SodiumException('Invalid MAC');
1215 }
1216
1217 /** @var string $m - Decrypted message */
1218 $m = ParagonIE_Sodium_Core_Util::xorStrings(
1219 ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES),
1220 ParagonIE_Sodium_Core_Util::substr($c, 0, self::secretbox_xchacha20poly1305_ZEROBYTES)
1221 );
1222
1223 if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) {
1224 // We had more than 1 block, so let's continue to decrypt the rest.
1225 $m .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
1226 ParagonIE_Sodium_Core_Util::substr(
1227 $c,
1228 self::secretbox_xchacha20poly1305_ZEROBYTES
1229 ),
1230 ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
1231 (string) $subkey,
1232 ParagonIE_Sodium_Core_Util::store64_le(1)
1233 );
1234 }
1235 return $m;
1236 }
1237
1238 /**
1239 * @param string $key
1240 * @return array<int, string> Returns a state and a header.
1241 * @throws Exception
1242 * @throws SodiumException
1243 */
1244 public static function secretstream_xchacha20poly1305_init_push($key)
1245 {
1246 # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
1247 $out = random_bytes(24);
1248
1249 # crypto_core_hchacha20(state->k, out, k, NULL);
1250 $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
1251 ParagonIE_Sodium_Core_Util::substr($out, 0, 16),
1252 $key
1253 );
1254 $state = new ParagonIE_Sodium_Core_SecretStream_State(
1255 $subkey,
1256 ParagonIE_Sodium_Core_Util::substr($out, 16, 8) . str_repeat("\0", 4)
1257 );
1258
1259 # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
1260 $state->counterReset();
1261
1262 # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
1263 # crypto_secretstream_xchacha20poly1305_INONCEBYTES);
1264 # memset(state->_pad, 0, sizeof state->_pad);
1265 return array(
1266 $state->toString(),
1267 $out
1268 );
1269 }
1270
1271 /**
1272 * @param string $key
1273 * @param string $header
1274 * @return string Returns a state.
1275 * @throws Exception
1276 */
1277 public static function secretstream_xchacha20poly1305_init_pull($key, $header)
1278 {
1279 # crypto_core_hchacha20(state->k, in, k, NULL);
1280 $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
1281 ParagonIE_Sodium_Core_Util::substr($header, 0, 16),
1282 $key
1283 );
1284 $state = new ParagonIE_Sodium_Core_SecretStream_State(
1285 $subkey,
1286 ParagonIE_Sodium_Core_Util::substr($header, 16)
1287 );
1288 $state->counterReset();
1289 # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
1290 # crypto_secretstream_xchacha20poly1305_INONCEBYTES);
1291 # memset(state->_pad, 0, sizeof state->_pad);
1292 # return 0;
1293 return $state->toString();
1294 }
1295
1296 /**
1297 * @param string $state
1298 * @param string $msg
1299 * @param string $aad
1300 * @param int $tag
1301 * @return string
1302 * @throws SodiumException
1303 */
1304 public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0)
1305 {
1306 $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
1307 # crypto_onetimeauth_poly1305_state poly1305_state;
1308 # unsigned char block[64U];
1309 # unsigned char slen[8U];
1310 # unsigned char *c;
1311 # unsigned char *mac;
1312
1313 $msglen = ParagonIE_Sodium_Core_Util::strlen($msg);
1314 $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad);
1315
1316 if ((($msglen + 63) >> 6) > 0xfffffffe) {
1317 throw new SodiumException(
1318 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
1319 );
1320 }
1321
1322 # if (outlen_p != NULL) {
1323 # *outlen_p = 0U;
1324 # }
1325 # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
1326 # sodium_misuse();
1327 # }
1328
1329 # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
1330 # crypto_onetimeauth_poly1305_init(&poly1305_state, block);
1331 # sodium_memzero(block, sizeof block);
1332 $auth = new ParagonIE_Sodium_Core_Poly1305_State(
1333 ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
1334 );
1335
1336 # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
1337 $auth->update($aad);
1338
1339 # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
1340 # (0x10 - adlen) & 0xf);
1341 $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));
1342
1343 # memset(block, 0, sizeof block);
1344 # block[0] = tag;
1345 # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
1346 # state->nonce, 1U, state->k);
1347 $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
1348 ParagonIE_Sodium_Core_Util::intToChr($tag) . str_repeat("\0", 63),
1349 $st->getCombinedNonce(),
1350 $st->getKey(),
1351 ParagonIE_Sodium_Core_Util::store64_le(1)
1352 );
1353
1354 # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
1355 $auth->update($block);
1356
1357 # out[0] = block[0];
1358 $out = $block[0];
1359 # c = out + (sizeof tag);
1360 # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
1361 $cipher = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
1362 $msg,
1363 $st->getCombinedNonce(),
1364 $st->getKey(),
1365 ParagonIE_Sodium_Core_Util::store64_le(2)
1366 );
1367
1368 # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
1369 $auth->update($cipher);
1370
1371 $out .= $cipher;
1372 unset($cipher);
1373
1374 # crypto_onetimeauth_poly1305_update
1375 # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
1376 $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));
1377
1378 # STORE64_LE(slen, (uint64_t) adlen);
1379 $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen);
1380
1381 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
1382 $auth->update($slen);
1383
1384 # STORE64_LE(slen, (sizeof block) + mlen);
1385 $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen);
1386
1387 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
1388 $auth->update($slen);
1389
1390 # mac = c + mlen;
1391 # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
1392 $mac = $auth->finish();
1393 $out .= $mac;
1394
1395 # sodium_memzero(&poly1305_state, sizeof poly1305_state);
1396 unset($auth);
1397
1398
1399 # XOR_BUF(STATE_INONCE(state), mac,
1400 # crypto_secretstream_xchacha20poly1305_INONCEBYTES);
1401 $st->xorNonce($mac);
1402
1403 # sodium_increment(STATE_COUNTER(state),
1404 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
1405 $st->incrementCounter();
1406 // Overwrite by reference:
1407 $state = $st->toString();
1408
1409 /** @var bool $rekey */
1410 $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
1411 # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
1412 # sodium_is_zero(STATE_COUNTER(state),
1413 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
1414 # crypto_secretstream_xchacha20poly1305_rekey(state);
1415 # }
1416 if ($rekey || $st->needsRekey()) {
1417 // DO REKEY
1418 self::secretstream_xchacha20poly1305_rekey($state);
1419 }
1420 # if (outlen_p != NULL) {
1421 # *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
1422 # }
1423 return $out;
1424 }
1425
1426 /**
1427 * @param string $state
1428 * @param string $cipher
1429 * @param string $aad
1430 * @return bool|array{0: string, 1: int}
1431 * @throws SodiumException
1432 */
1433 public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '')
1434 {
1435 $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
1436
1437 $cipherlen = ParagonIE_Sodium_Core_Util::strlen($cipher);
1438 # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
1439 $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
1440 $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad);
1441
1442 # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
1443 # sodium_misuse();
1444 # }
1445 if ((($msglen + 63) >> 6) > 0xfffffffe) {
1446 throw new SodiumException(
1447 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
1448 );
1449 }
1450
1451 # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
1452 # crypto_onetimeauth_poly1305_init(&poly1305_state, block);
1453 # sodium_memzero(block, sizeof block);
1454 $auth = new ParagonIE_Sodium_Core_Poly1305_State(
1455 ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
1456 );
1457
1458 # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
1459 $auth->update($aad);
1460
1461 # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
1462 # (0x10 - adlen) & 0xf);
1463 $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));
1464
1465
1466 # memset(block, 0, sizeof block);
1467 # block[0] = in[0];
1468 # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
1469 # state->nonce, 1U, state->k);
1470 $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
1471 $cipher[0] . str_repeat("\0", 63),
1472 $st->getCombinedNonce(),
1473 $st->getKey(),
1474 ParagonIE_Sodium_Core_Util::store64_le(1)
1475 );
1476 # tag = block[0];
1477 # block[0] = in[0];
1478 # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
1479 $tag = ParagonIE_Sodium_Core_Util::chrToInt($block[0]);
1480 $block[0] = $cipher[0];
1481 $auth->update($block);
1482
1483
1484 # c = in + (sizeof tag);
1485 # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
1486 $auth->update(ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen));
1487
1488 # crypto_onetimeauth_poly1305_update
1489 # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
1490 $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));
1491
1492 # STORE64_LE(slen, (uint64_t) adlen);
1493 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
1494 $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen);
1495 $auth->update($slen);
1496
1497 # STORE64_LE(slen, (sizeof block) + mlen);
1498 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
1499 $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen);
1500 $auth->update($slen);
1501
1502 # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
1503 # sodium_memzero(&poly1305_state, sizeof poly1305_state);
1504 $mac = $auth->finish();
1505
1506 # stored_mac = c + mlen;
1507 # if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
1508 # sodium_memzero(mac, sizeof mac);
1509 # return -1;
1510 # }
1511
1512 $stored = ParagonIE_Sodium_Core_Util::substr($cipher, $msglen + 1, 16);
1513 if (!ParagonIE_Sodium_Core_Util::hashEquals($mac, $stored)) {
1514 return false;
1515 }
1516
1517 # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
1518 $out = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
1519 ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen),
1520 $st->getCombinedNonce(),
1521 $st->getKey(),
1522 ParagonIE_Sodium_Core_Util::store64_le(2)
1523 );
1524
1525 # XOR_BUF(STATE_INONCE(state), mac,
1526 # crypto_secretstream_xchacha20poly1305_INONCEBYTES);
1527 $st->xorNonce($mac);
1528
1529 # sodium_increment(STATE_COUNTER(state),
1530 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
1531 $st->incrementCounter();
1532
1533 # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
1534 # sodium_is_zero(STATE_COUNTER(state),
1535 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
1536 # crypto_secretstream_xchacha20poly1305_rekey(state);
1537 # }
1538
1539 // Overwrite by reference:
1540 $state = $st->toString();
1541
1542 /** @var bool $rekey */
1543 $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
1544 if ($rekey || $st->needsRekey()) {
1545 // DO REKEY
1546 self::secretstream_xchacha20poly1305_rekey($state);
1547 }
1548 return array($out, $tag);
1549 }
1550
1551 /**
1552 * @param string $state
1553 * @return void
1554 * @throws SodiumException
1555 */
1556 public static function secretstream_xchacha20poly1305_rekey(&$state)
1557 {
1558 $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
1559 # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
1560 # crypto_secretstream_xchacha20poly1305_INONCEBYTES];
1561 # size_t i;
1562 # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
1563 # new_key_and_inonce[i] = state->k[i];
1564 # }
1565 $new_key_and_inonce = $st->getKey();
1566
1567 # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
1568 # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
1569 # STATE_INONCE(state)[i];
1570 # }
1571 $new_key_and_inonce .= ParagonIE_Sodium_Core_Util::substR($st->getNonce(), 0, 8);
1572
1573 # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
1574 # sizeof new_key_and_inonce,
1575 # state->nonce, state->k);
1576
1577 $st->rekey(ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
1578 $new_key_and_inonce,
1579 $st->getCombinedNonce(),
1580 $st->getKey(),
1581 ParagonIE_Sodium_Core_Util::store64_le(0)
1582 ));
1583
1584 # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
1585 # state->k[i] = new_key_and_inonce[i];
1586 # }
1587 # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
1588 # STATE_INONCE(state)[i] =
1589 # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i];
1590 # }
1591 # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
1592 $st->counterReset();
1593
1594 $state = $st->toString();
1595 }
1596
1597 /**
1598 * Detached Ed25519 signature.
1599 *
1600 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1601 *
1602 * @param string $message
1603 * @param string $sk
1604 * @return string
1605 * @throws SodiumException
1606 * @throws TypeError
1607 */
1608 public static function sign_detached($message, $sk)
1609 {
1610 return ParagonIE_Sodium_Core_Ed25519::sign_detached($message, $sk);
1611 }
1612
1613 /**
1614 * Attached Ed25519 signature. (Returns a signed message.)
1615 *
1616 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1617 *
1618 * @param string $message
1619 * @param string $sk
1620 * @return string
1621 * @throws SodiumException
1622 * @throws TypeError
1623 */
1624 public static function sign($message, $sk)
1625 {
1626 return ParagonIE_Sodium_Core_Ed25519::sign($message, $sk);
1627 }
1628
1629 /**
1630 * Opens a signed message. If valid, returns the message.
1631 *
1632 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1633 *
1634 * @param string $signedMessage
1635 * @param string $pk
1636 * @return string
1637 * @throws SodiumException
1638 * @throws TypeError
1639 */
1640 public static function sign_open($signedMessage, $pk)
1641 {
1642 return ParagonIE_Sodium_Core_Ed25519::sign_open($signedMessage, $pk);
1643 }
1644
1645 /**
1646 * Verify a detached signature of a given message and public key.
1647 *
1648 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1649 *
1650 * @param string $signature
1651 * @param string $message
1652 * @param string $pk
1653 * @return bool
1654 * @throws SodiumException
1655 * @throws TypeError
1656 */
1657 public static function sign_verify_detached($signature, $message, $pk)
1658 {
1659 return ParagonIE_Sodium_Core_Ed25519::verify_detached($signature, $message, $pk);
1660 }
1661}
1662
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1