Completed
Push — develop ( f0d100...266ee2 )
by J.D.
04:14
created
src/library/sodium_compat/src/Crypto32.php 1 patch
Indentation   +1158 added lines, -1158 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Crypto32', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -14,1161 +14,1161 @@  discard block
 block discarded – undo
14 14
  */
15 15
 abstract class ParagonIE_Sodium_Crypto32
16 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 Error
69
-     */
70
-    public static function aead_chacha20poly1305_decrypt(
71
-        $message = '',
72
-        $ad = '',
73
-        $nonce = '',
74
-        $key = ''
75
-    ) {
76
-        /** @var int $len - Length of message (ciphertext + MAC) */
77
-        $len = ParagonIE_Sodium_Core32_Util::strlen($message);
78
-
79
-        /** @var int  $clen - Length of ciphertext */
80
-        $clen = $len - self::aead_chacha20poly1305_ABYTES;
81
-
82
-        /** @var int $adlen - Length of associated data */
83
-        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
84
-
85
-        /** @var string $mac - Message authentication code */
86
-        $mac = ParagonIE_Sodium_Core32_Util::substr(
87
-            $message,
88
-            $clen,
89
-            self::aead_chacha20poly1305_ABYTES
90
-        );
91
-
92
-        /** @var string $ciphertext - The encrypted message (sans MAC) */
93
-        $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 0, $clen);
94
-
95
-        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
96
-        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
97
-            32,
98
-            $nonce,
99
-            $key
100
-        );
101
-
102
-        /* Recalculate the Poly1305 authentication tag (MAC): */
103
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
104
-        try {
105
-            ParagonIE_Sodium_Compat::memzero($block0);
106
-        } catch (Error $ex) {
107
-            $block0 = null;
108
-        }
109
-        $state->update($ad);
110
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
111
-        $state->update($ciphertext);
112
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
113
-        $computed_mac = $state->finish();
114
-
115
-        /* Compare the given MAC with the recalculated MAC: */
116
-        if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) {
117
-            throw new Error('Invalid MAC');
118
-        }
119
-
120
-        // Here, we know that the MAC is valid, so we decrypt and return the plaintext
121
-        return ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
122
-            $ciphertext,
123
-            $nonce,
124
-            $key,
125
-            ParagonIE_Sodium_Core32_Util::store64_le(1)
126
-        );
127
-    }
128
-
129
-    /**
130
-     * AEAD Encryption with ChaCha20-Poly1305
131
-     *
132
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
133
-     *
134
-     * @param string $message
135
-     * @param string $ad
136
-     * @param string $nonce
137
-     * @param string $key
138
-     * @return string
139
-     */
140
-    public static function aead_chacha20poly1305_encrypt(
141
-        $message = '',
142
-        $ad = '',
143
-        $nonce = '',
144
-        $key = ''
145
-    ) {
146
-        /** @var int $len - Length of the plaintext message */
147
-        $len = ParagonIE_Sodium_Core32_Util::strlen($message);
148
-
149
-        /** @var int $adlen - Length of the associated data */
150
-        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
151
-
152
-        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
153
-        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
154
-            32,
155
-            $nonce,
156
-            $key
157
-        );
158
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
159
-        try {
160
-            ParagonIE_Sodium_Compat::memzero($block0);
161
-        } catch (Error $ex) {
162
-            $block0 = null;
163
-        }
164
-
165
-        /** @var string $ciphertext - Raw encrypted data */
166
-        $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
167
-            $message,
168
-            $nonce,
169
-            $key,
170
-            ParagonIE_Sodium_Core32_Util::store64_le(1)
171
-        );
172
-
173
-        $state->update($ad);
174
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
175
-        $state->update($ciphertext);
176
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
177
-        return $ciphertext . $state->finish();
178
-    }
179
-
180
-    /**
181
-     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
182
-     *
183
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
184
-     *
185
-     * @param string $message
186
-     * @param string $ad
187
-     * @param string $nonce
188
-     * @param string $key
189
-     * @return string
190
-     * @throws Error
191
-     */
192
-    public static function aead_chacha20poly1305_ietf_decrypt(
193
-        $message = '',
194
-        $ad = '',
195
-        $nonce = '',
196
-        $key = ''
197
-    ) {
198
-        /** @var int $adlen - Length of associated data */
199
-        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
200
-
201
-        /** @var int $len - Length of message (ciphertext + MAC) */
202
-        $len = ParagonIE_Sodium_Core32_Util::strlen($message);
203
-
204
-        /** @var int  $clen - Length of ciphertext */
205
-        $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES;
206
-
207
-        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
208
-        $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
209
-            32,
210
-            $nonce,
211
-            $key
212
-        );
213
-
214
-        /** @var string $mac - Message authentication code */
215
-        $mac = ParagonIE_Sodium_Core32_Util::substr(
216
-            $message,
217
-            $len - self::aead_chacha20poly1305_IETF_ABYTES,
218
-            self::aead_chacha20poly1305_IETF_ABYTES
219
-        );
220
-
221
-        /** @var string $ciphertext - The encrypted message (sans MAC) */
222
-        $ciphertext = ParagonIE_Sodium_Core32_Util::substr(
223
-            $message,
224
-            0,
225
-            $len - self::aead_chacha20poly1305_IETF_ABYTES
226
-        );
227
-
228
-        /* Recalculate the Poly1305 authentication tag (MAC): */
229
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
230
-        try {
231
-            ParagonIE_Sodium_Compat::memzero($block0);
232
-        } catch (Error $ex) {
233
-            $block0 = null;
234
-        }
235
-        $state->update($ad);
236
-        $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
237
-        $state->update($ciphertext);
238
-        $state->update(str_repeat("\x00", (0x10 - $clen) & 0xf));
239
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
240
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
241
-        $computed_mac = $state->finish();
242
-
243
-        /* Compare the given MAC with the recalculated MAC: */
244
-        if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) {
245
-            throw new Error('Invalid MAC');
246
-        }
247
-
248
-        // Here, we know that the MAC is valid, so we decrypt and return the plaintext
249
-        return ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
250
-            $ciphertext,
251
-            $nonce,
252
-            $key,
253
-            ParagonIE_Sodium_Core32_Util::store64_le(1)
254
-        );
255
-    }
256
-
257
-    /**
258
-     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
259
-     *
260
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
261
-     *
262
-     * @param string $message
263
-     * @param string $ad
264
-     * @param string $nonce
265
-     * @param string $key
266
-     * @return string
267
-     */
268
-    public static function aead_chacha20poly1305_ietf_encrypt(
269
-        $message = '',
270
-        $ad = '',
271
-        $nonce = '',
272
-        $key = ''
273
-    ) {
274
-        /** @var int $len - Length of the plaintext message */
275
-        $len = ParagonIE_Sodium_Core32_Util::strlen($message);
276
-
277
-        /** @var int $adlen - Length of the associated data */
278
-        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
279
-
280
-        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
281
-        $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
282
-            32,
283
-            $nonce,
284
-            $key
285
-        );
286
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
287
-        try {
288
-            ParagonIE_Sodium_Compat::memzero($block0);
289
-        } catch (Error $ex) {
290
-            $block0 = null;
291
-        }
292
-
293
-        /** @var string $ciphertext - Raw encrypted data */
294
-        $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
295
-            $message,
296
-            $nonce,
297
-            $key,
298
-            ParagonIE_Sodium_Core32_Util::store64_le(1)
299
-        );
300
-
301
-        $state->update($ad);
302
-        $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
303
-        $state->update($ciphertext);
304
-        $state->update(str_repeat("\x00", ((0x10 - $len) & 0xf)));
305
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
306
-        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
307
-        return $ciphertext . $state->finish();
308
-    }
309
-
310
-    /**
311
-     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
312
-     *
313
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
314
-     *
315
-     * @param string $message
316
-     * @param string $ad
317
-     * @param string $nonce
318
-     * @param string $key
319
-     * @return string
320
-     * @throws Error
321
-     */
322
-    public static function aead_xchacha20poly1305_ietf_decrypt(
323
-        $message = '',
324
-        $ad = '',
325
-        $nonce = '',
326
-        $key = ''
327
-    ) {
328
-        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
329
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
330
-            $key
331
-        );
332
-        $nonceLast = "\x00\x00\x00\x00" .
333
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);
334
-
335
-        return self::aead_chacha20poly1305_ietf_decrypt($message, $ad, $nonceLast, $subkey);
336
-    }
337
-
338
-    /**
339
-     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
340
-     *
341
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
342
-     *
343
-     * @param string $message
344
-     * @param string $ad
345
-     * @param string $nonce
346
-     * @param string $key
347
-     * @return string
348
-     */
349
-    public static function aead_xchacha20poly1305_ietf_encrypt(
350
-        $message = '',
351
-        $ad = '',
352
-        $nonce = '',
353
-        $key = ''
354
-    ) {
355
-        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
356
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
357
-            $key
358
-        );
359
-        $nonceLast = "\x00\x00\x00\x00" .
360
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);
361
-
362
-        return self::aead_chacha20poly1305_ietf_encrypt($message, $ad, $nonceLast, $subkey);
363
-    }
364
-
365
-    /**
366
-     * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
367
-     *
368
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
369
-     *
370
-     * @param string $message
371
-     * @param string $key
372
-     * @return string
373
-     */
374
-    public static function auth($message, $key)
375
-    {
376
-        return ParagonIE_Sodium_Core32_Util::substr(
377
-            hash_hmac('sha512', $message, $key, true),
378
-            0,
379
-            32
380
-        );
381
-    }
382
-
383
-    /**
384
-     * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
385
-     *
386
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
387
-     *
388
-     * @param string $mac
389
-     * @param string $message
390
-     * @param string $key
391
-     * @return bool
392
-     */
393
-    public static function auth_verify($mac, $message, $key)
394
-    {
395
-        return ParagonIE_Sodium_Core32_Util::hashEquals(
396
-            $mac,
397
-            self::auth($message, $key)
398
-        );
399
-    }
400
-
401
-    /**
402
-     * X25519 key exchange followed by XSalsa20Poly1305 symmetric encryption
403
-     *
404
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
405
-     *
406
-     * @param string $plaintext
407
-     * @param string $nonce
408
-     * @param string $keypair
409
-     * @return string
410
-     */
411
-    public static function box($plaintext, $nonce, $keypair)
412
-    {
413
-        $c = self::secretbox(
414
-            $plaintext,
415
-            $nonce,
416
-            self::box_beforenm(
417
-                self::box_secretkey($keypair),
418
-                self::box_publickey($keypair)
419
-            )
420
-        );
421
-        return $c;
422
-    }
423
-
424
-    /**
425
-     * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair.
426
-     *
427
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
428
-     *
429
-     * @param string $message
430
-     * @param string $publicKey
431
-     * @return string
432
-     */
433
-    public static function box_seal($message, $publicKey)
434
-    {
435
-        /** @var string $ephemeralKeypair */
436
-        $ephemeralKeypair = self::box_keypair();
437
-
438
-        /** @var string $ephemeralSK */
439
-        $ephemeralSK = self::box_secretkey($ephemeralKeypair);
440
-
441
-        /** @var string $ephemeralPK */
442
-        $ephemeralPK = self::box_publickey($ephemeralKeypair);
443
-
444
-        /** @var string $nonce */
445
-        $nonce = self::generichash(
446
-            $ephemeralPK . $publicKey,
447
-            '',
448
-            24
449
-        );
450
-
451
-        /** @var string $keypair - The combined keypair used in crypto_box() */
452
-        $keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);
453
-
454
-        /** @var string $ciphertext Ciphertext + MAC from crypto_box */
455
-        $ciphertext = self::box($message, $nonce, $keypair);
456
-        try {
457
-            ParagonIE_Sodium_Compat::memzero($ephemeralKeypair);
458
-            ParagonIE_Sodium_Compat::memzero($ephemeralSK);
459
-            ParagonIE_Sodium_Compat::memzero($nonce);
460
-        } catch (Error $ex) {
461
-            $ephemeralKeypair = null;
462
-            $ephemeralSK = null;
463
-            $nonce = null;
464
-        }
465
-        return $ephemeralPK . $ciphertext;
466
-    }
467
-
468
-    /**
469
-     * Opens a message encrypted via box_seal().
470
-     *
471
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
472
-     *
473
-     * @param string $message
474
-     * @param string $keypair
475
-     * @return string
476
-     */
477
-    public static function box_seal_open($message, $keypair)
478
-    {
479
-        /** @var string $ephemeralPK */
480
-        $ephemeralPK = ParagonIE_Sodium_Core32_Util::substr($message, 0, 32);
481
-
482
-        /** @var string $ciphertext (ciphertext + MAC) */
483
-        $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 32);
484
-
485
-        /** @var string $secretKey */
486
-        $secretKey = self::box_secretkey($keypair);
487
-
488
-        /** @var string $publicKey */
489
-        $publicKey = self::box_publickey($keypair);
490
-
491
-        /** @var string $nonce */
492
-        $nonce = self::generichash(
493
-            $ephemeralPK . $publicKey,
494
-            '',
495
-            24
496
-        );
497
-
498
-        /** @var string $keypair */
499
-        $keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);
500
-
501
-        /** @var string $m */
502
-        $m = self::box_open($ciphertext, $nonce, $keypair);
503
-        try {
504
-            ParagonIE_Sodium_Compat::memzero($secretKey);
505
-            ParagonIE_Sodium_Compat::memzero($ephemeralPK);
506
-            ParagonIE_Sodium_Compat::memzero($nonce);
507
-        } catch (Error $ex) {
508
-            $secretKey = null;
509
-            $ephemeralPK = null;
510
-            $nonce = null;
511
-        }
512
-        return $m;
513
-    }
514
-
515
-    /**
516
-     * Used by crypto_box() to get the crypto_secretbox() key.
517
-     *
518
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
519
-     *
520
-     * @param string $sk
521
-     * @param string $pk
522
-     * @return string
523
-     */
524
-    public static function box_beforenm($sk, $pk)
525
-    {
526
-        return ParagonIE_Sodium_Core32_HSalsa20::hsalsa20(
527
-            str_repeat("\x00", 16),
528
-            self::scalarmult($sk, $pk)
529
-        );
530
-    }
531
-
532
-    /**
533
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
534
-     *
535
-     * @return string
536
-     */
537
-    public static function box_keypair()
538
-    {
539
-        $sKey = random_bytes(32);
540
-        $pKey = self::scalarmult_base($sKey);
541
-        return $sKey . $pKey;
542
-    }
543
-
544
-    /**
545
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
546
-     *
547
-     * @param string $sKey
548
-     * @param string $pKey
549
-     * @return string
550
-     */
551
-    public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey)
552
-    {
553
-        return ParagonIE_Sodium_Core32_Util::substr($sKey, 0, 32) .
554
-            ParagonIE_Sodium_Core32_Util::substr($pKey, 0, 32);
555
-    }
556
-
557
-    /**
558
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
559
-     *
560
-     * @param string $keypair
561
-     * @return string
562
-     * @throws RangeException
563
-     */
564
-    public static function box_secretkey($keypair)
565
-    {
566
-        if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== 64) {
567
-            throw new RangeException('Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.');
568
-        }
569
-        return ParagonIE_Sodium_Core32_Util::substr($keypair, 0, 32);
570
-    }
571
-
572
-    /**
573
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
574
-     *
575
-     * @param string $keypair
576
-     * @return string
577
-     * @throws RangeException
578
-     */
579
-    public static function box_publickey($keypair)
580
-    {
581
-        if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
582
-            throw new RangeException('Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.');
583
-        }
584
-        return ParagonIE_Sodium_Core32_Util::substr($keypair, 32, 32);
585
-    }
586
-
587
-    /**
588
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
589
-     *
590
-     * @param string $sKey
591
-     * @return string
592
-     * @throws RangeException
593
-     */
594
-    public static function box_publickey_from_secretkey($sKey)
595
-    {
596
-        if (ParagonIE_Sodium_Core32_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) {
597
-            throw new RangeException('Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.');
598
-        }
599
-        return self::scalarmult_base($sKey);
600
-    }
601
-
602
-    /**
603
-     * Decrypt a message encrypted with box().
604
-     *
605
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
606
-     *
607
-     * @param string $ciphertext
608
-     * @param string $nonce
609
-     * @param string $nonce
610
-     * @param string $keypair
611
-     * @return string
612
-     */
613
-    public static function box_open($ciphertext, $nonce, $keypair)
614
-    {
615
-        return self::secretbox_open(
616
-            $ciphertext,
617
-            $nonce,
618
-            self::box_beforenm(
619
-                self::box_secretkey($keypair),
620
-                self::box_publickey($keypair)
621
-            )
622
-        );
623
-    }
624
-
625
-    /**
626
-     * Calculate a BLAKE2b hash.
627
-     *
628
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
629
-     *
630
-     * @param string $message
631
-     * @param string|null $key
632
-     * @param int $outlen
633
-     * @return string
634
-     * @throws RangeException
635
-     */
636
-    public static function generichash($message, $key = '', $outlen = 32)
637
-    {
638
-        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
639
-        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
640
-
641
-        $k = null;
642
-        if (!empty($key)) {
643
-            /** @var SplFixedArray $k */
644
-            $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
645
-            if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
646
-                throw new RangeException('Invalid key size');
647
-            }
648
-        }
649
-
650
-        /** @var SplFixedArray $in */
651
-        $in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);
652
-
653
-        /** @var SplFixedArray $ctx */
654
-        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outlen);
655
-        ParagonIE_Sodium_Core32_BLAKE2b::update($ctx, $in, $in->count());
656
-
657
-        /** @var SplFixedArray $out */
658
-        $out = new SplFixedArray($outlen);
659
-        $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($ctx, $out);
660
-
661
-        /** @var array<int, int> */
662
-        $outArray = $out->toArray();
663
-        return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
664
-    }
665
-
666
-    /**
667
-     * Finalize a BLAKE2b hashing context, returning the hash.
668
-     *
669
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
670
-     *
671
-     * @param string $ctx
672
-     * @param int $outlen
673
-     * @return string
674
-     * @throws TypeError
675
-     */
676
-    public static function generichash_final($ctx, $outlen = 32)
677
-    {
678
-        if (!is_string($ctx)) {
679
-            throw new TypeError('Context must be a string');
680
-        }
681
-        $out = new SplFixedArray($outlen);
682
-
683
-        /** @var SplFixedArray $context */
684
-        $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);
685
-
686
-        /** @var SplFixedArray $out */
687
-        $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($context, $out);
688
-
689
-        /** @var array<int, int> */
690
-        $outArray = $out->toArray();
691
-        return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
692
-    }
693
-
694
-    /**
695
-     * Initialize a hashing context for BLAKE2b.
696
-     *
697
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
698
-     *
699
-     * @param string $key
700
-     * @param int $outputLength
701
-     * @return string
702
-     * @throws RangeException
703
-     */
704
-    public static function generichash_init($key = '', $outputLength = 32)
705
-    {
706
-        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
707
-        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
708
-
709
-        $k = null;
710
-        if (!empty($key)) {
711
-            $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
712
-            if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
713
-                throw new RangeException('Invalid key size');
714
-            }
715
-        }
716
-
717
-        /** @var SplFixedArray $ctx */
718
-        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength);
719
-
720
-        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
721
-    }
722
-
723
-    /**
724
-     * Update a hashing context for BLAKE2b with $message
725
-     *
726
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
727
-     *
728
-     * @param string $ctx
729
-     * @param string $message
730
-     * @return string
731
-     */
732
-    public static function generichash_update($ctx, $message)
733
-    {
734
-        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
735
-        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
736
-
737
-        /** @var SplFixedArray $context */
738
-        $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);
739
-
740
-        /** @var SplFixedArray $in */
741
-        $in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);
742
-
743
-        ParagonIE_Sodium_Core32_BLAKE2b::update($context, $in, $in->count());
744
-
745
-        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($context);
746
-    }
747
-
748
-    /**
749
-     * Libsodium's crypto_kx().
750
-     *
751
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
752
-     *
753
-     * @param string $my_sk
754
-     * @param string $their_pk
755
-     * @param string $client_pk
756
-     * @param string $server_pk
757
-     * @return string
758
-     */
759
-    public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk)
760
-    {
761
-        return self::generichash(
762
-            self::scalarmult($my_sk, $their_pk) .
763
-            $client_pk .
764
-            $server_pk
765
-        );
766
-    }
767
-
768
-    /**
769
-     * ECDH over Curve25519
770
-     *
771
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
772
-     *
773
-     * @param string $sKey
774
-     * @param string $pKey
775
-     * @return string
776
-     *
777
-     * @throws Error
778
-     */
779
-    public static function scalarmult($sKey, $pKey)
780
-    {
781
-        $q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey);
782
-        self::scalarmult_throw_if_zero($q);
783
-        return $q;
784
-    }
785
-
786
-    /**
787
-     * ECDH over Curve25519, using the basepoint.
788
-     * Used to get a secret key from a public key.
789
-     *
790
-     * @param string $secret
791
-     * @return string
792
-     *
793
-     * @throws Error
794
-     */
795
-    public static function scalarmult_base($secret)
796
-    {
797
-        $q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
798
-        self::scalarmult_throw_if_zero($q);
799
-        return $q;
800
-    }
801
-
802
-    /**
803
-     * This throws an Error if a zero public key was passed to the function.
804
-     *
805
-     * @param string $q
806
-     * @return void
807
-     * @throws Error
808
-     */
809
-    protected static function scalarmult_throw_if_zero($q)
810
-    {
811
-        $d = 0;
812
-        for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
813
-            $d |= ParagonIE_Sodium_Core32_Util::chrToInt($q[$i]);
814
-        }
815
-
816
-        /* branch-free variant of === 0 */
817
-        if (-(1 & (($d - 1) >> 8))) {
818
-            throw new Error('Zero public key is not allowed');
819
-        }
820
-    }
821
-
822
-    /**
823
-     * XSalsa20-Poly1305 authenticated symmetric-key encryption.
824
-     *
825
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
826
-     *
827
-     * @param string $plaintext
828
-     * @param string $nonce
829
-     * @param string $key
830
-     * @return string
831
-     */
832
-    public static function secretbox($plaintext, $nonce, $key)
833
-    {
834
-        /** @var string $subkey */
835
-        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);
836
-
837
-        /** @var string $block0 */
838
-        $block0 = str_repeat("\x00", 32);
839
-
840
-        /** @var int $mlen - Length of the plaintext message */
841
-        $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
842
-        $mlen0 = $mlen;
843
-        if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
844
-            $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
845
-        }
846
-        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0);
847
-
848
-        /** @var string $block0 */
849
-        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor(
850
-            $block0,
851
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
852
-            $subkey
853
-        );
854
-
855
-        /** @var string $c */
856
-        $c = ParagonIE_Sodium_Core32_Util::substr(
857
-            $block0,
858
-            self::secretbox_xsalsa20poly1305_ZEROBYTES
859
-        );
860
-        if ($mlen > $mlen0) {
861
-            $c .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
862
-                ParagonIE_Sodium_Core32_Util::substr(
863
-                    $plaintext,
864
-                    self::secretbox_xsalsa20poly1305_ZEROBYTES
865
-                ),
866
-                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
867
-                1,
868
-                $subkey
869
-            );
870
-        }
871
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
872
-            ParagonIE_Sodium_Core32_Util::substr(
873
-                $block0,
874
-                0,
875
-                self::onetimeauth_poly1305_KEYBYTES
876
-            )
877
-        );
878
-        try {
879
-            ParagonIE_Sodium_Compat::memzero($block0);
880
-            ParagonIE_Sodium_Compat::memzero($subkey);
881
-        } catch (Error $ex) {
882
-            $block0 = null;
883
-            $subkey = null;
884
-        }
885
-
886
-        $state->update($c);
887
-
888
-        /** @var string $c - MAC || ciphertext */
889
-        $c = $state->finish() . $c;
890
-        unset($state);
891
-
892
-        return $c;
893
-    }
894
-
895
-    /**
896
-     * Decrypt a ciphertext generated via secretbox().
897
-     *
898
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
899
-     *
900
-     * @param string $ciphertext
901
-     * @param string $nonce
902
-     * @param string $key
903
-     * @return string
904
-     * @throws Error
905
-     */
906
-    public static function secretbox_open($ciphertext, $nonce, $key)
907
-    {
908
-        /** @var string $mac */
909
-        $mac = ParagonIE_Sodium_Core32_Util::substr(
910
-            $ciphertext,
911
-            0,
912
-            self::secretbox_xsalsa20poly1305_MACBYTES
913
-        );
914
-
915
-        /** @var string $c */
916
-        $c = ParagonIE_Sodium_Core32_Util::substr(
917
-            $ciphertext,
918
-            self::secretbox_xsalsa20poly1305_MACBYTES
919
-        );
920
-
921
-        /** @var int $clen */
922
-        $clen = ParagonIE_Sodium_Core32_Util::strlen($c);
923
-
924
-        /** @var string $subkey */
925
-        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);
926
-
927
-        /** @var string $block0 */
928
-        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20(
929
-            64,
930
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
931
-            $subkey
932
-        );
933
-        $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
934
-            $mac,
935
-            $c,
936
-            ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
937
-        );
938
-        if (!$verified) {
939
-            try {
940
-                ParagonIE_Sodium_Compat::memzero($subkey);
941
-            } catch (Error $ex) {
942
-                $subkey = null;
943
-            }
944
-            throw new Error('Invalid MAC');
945
-        }
946
-
947
-        /** @var string $m - Decrypted message */
948
-        $m = ParagonIE_Sodium_Core32_Util::xorStrings(
949
-            ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES),
950
-            ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES)
951
-        );
952
-        if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
953
-            // We had more than 1 block, so let's continue to decrypt the rest.
954
-            $m .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
955
-                ParagonIE_Sodium_Core32_Util::substr(
956
-                    $c,
957
-                    self::secretbox_xsalsa20poly1305_ZEROBYTES
958
-                ),
959
-                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
960
-                1,
961
-                $subkey
962
-            );
963
-        }
964
-        return $m;
965
-    }
966
-
967
-    /**
968
-     * XChaCha20-Poly1305 authenticated symmetric-key encryption.
969
-     *
970
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
971
-     *
972
-     * @param string $plaintext
973
-     * @param string $nonce
974
-     * @param string $key
975
-     * @return string
976
-     */
977
-    public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key)
978
-    {
979
-        /** @var string $subkey */
980
-        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
981
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
982
-            $key
983
-        );
984
-        $nonceLast = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);
985
-
986
-        /** @var string $block0 */
987
-        $block0 = str_repeat("\x00", 32);
988
-
989
-        /** @var int $mlen - Length of the plaintext message */
990
-        $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
991
-        $mlen0 = $mlen;
992
-        if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) {
993
-            $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES;
994
-        }
995
-        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0);
996
-
997
-        /** @var string $block0 */
998
-        $block0 = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
999
-            $block0,
1000
-            $nonceLast,
1001
-            $subkey
1002
-        );
1003
-
1004
-        /** @var string $c */
1005
-        $c = ParagonIE_Sodium_Core32_Util::substr(
1006
-            $block0,
1007
-            self::secretbox_xchacha20poly1305_ZEROBYTES
1008
-        );
1009
-        if ($mlen > $mlen0) {
1010
-            $c .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
1011
-                ParagonIE_Sodium_Core32_Util::substr(
1012
-                    $plaintext,
1013
-                    self::secretbox_xchacha20poly1305_ZEROBYTES
1014
-                ),
1015
-                $nonceLast,
1016
-                $subkey,
1017
-                ParagonIE_Sodium_Core32_Util::store64_le(1)
1018
-            );
1019
-        }
1020
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
1021
-            ParagonIE_Sodium_Core32_Util::substr(
1022
-                $block0,
1023
-                0,
1024
-                self::onetimeauth_poly1305_KEYBYTES
1025
-            )
1026
-        );
1027
-        try {
1028
-            ParagonIE_Sodium_Compat::memzero($block0);
1029
-            ParagonIE_Sodium_Compat::memzero($subkey);
1030
-        } catch (Error $ex) {
1031
-            $block0 = null;
1032
-            $subkey = null;
1033
-        }
1034
-
1035
-        $state->update($c);
1036
-
1037
-        /** @var string $c - MAC || ciphertext */
1038
-        $c = $state->finish() . $c;
1039
-        unset($state);
1040
-
1041
-        return $c;
1042
-    }
1043
-
1044
-    /**
1045
-     * Decrypt a ciphertext generated via secretbox_xchacha20poly1305().
1046
-     *
1047
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1048
-     *
1049
-     * @param string $ciphertext
1050
-     * @param string $nonce
1051
-     * @param string $key
1052
-     * @return string
1053
-     * @throws Error
1054
-     */
1055
-    public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key)
1056
-    {
1057
-        /** @var string $mac */
1058
-        $mac = ParagonIE_Sodium_Core32_Util::substr(
1059
-            $ciphertext,
1060
-            0,
1061
-            self::secretbox_xchacha20poly1305_MACBYTES
1062
-        );
1063
-
1064
-        /** @var string $c */
1065
-        $c = ParagonIE_Sodium_Core32_Util::substr(
1066
-            $ciphertext,
1067
-            self::secretbox_xchacha20poly1305_MACBYTES
1068
-        );
1069
-
1070
-        /** @var int $clen */
1071
-        $clen = ParagonIE_Sodium_Core32_Util::strlen($c);
1072
-
1073
-        /** @var string $subkey */
1074
-        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hchacha20($nonce, $key);
1075
-
1076
-        /** @var string $block0 */
1077
-        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
1078
-            64,
1079
-            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
1080
-            $subkey
1081
-        );
1082
-        $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
1083
-            $mac,
1084
-            $c,
1085
-            ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
1086
-        );
1087
-
1088
-        if (!$verified) {
1089
-            try {
1090
-                ParagonIE_Sodium_Compat::memzero($subkey);
1091
-            } catch (Error $ex) {
1092
-                $subkey = null;
1093
-            }
1094
-            throw new Error('Invalid MAC');
1095
-        }
1096
-
1097
-        /** @var string $m - Decrypted message */
1098
-        $m = ParagonIE_Sodium_Core32_Util::xorStrings(
1099
-            ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES),
1100
-            ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xchacha20poly1305_ZEROBYTES)
1101
-        );
1102
-
1103
-        if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) {
1104
-            // We had more than 1 block, so let's continue to decrypt the rest.
1105
-            $m .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
1106
-                ParagonIE_Sodium_Core32_Util::substr(
1107
-                    $c,
1108
-                    self::secretbox_xchacha20poly1305_ZEROBYTES
1109
-                ),
1110
-                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
1111
-                $subkey,
1112
-                ParagonIE_Sodium_Core32_Util::store64_le(1)
1113
-            );
1114
-        }
1115
-        return $m;
1116
-    }
1117
-
1118
-    /**
1119
-     * Detached Ed25519 signature.
1120
-     *
1121
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1122
-     *
1123
-     * @param string $message
1124
-     * @param string $sk
1125
-     * @return string
1126
-     */
1127
-    public static function sign_detached($message, $sk)
1128
-    {
1129
-        return ParagonIE_Sodium_Core32_Ed25519::sign_detached($message, $sk);
1130
-    }
1131
-
1132
-    /**
1133
-     * Attached Ed25519 signature. (Returns a signed message.)
1134
-     *
1135
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1136
-     *
1137
-     * @param string $message
1138
-     * @param string $sk
1139
-     * @return string
1140
-     */
1141
-    public static function sign($message, $sk)
1142
-    {
1143
-        return ParagonIE_Sodium_Core32_Ed25519::sign($message, $sk);
1144
-    }
1145
-
1146
-    /**
1147
-     * Opens a signed message. If valid, returns the message.
1148
-     *
1149
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1150
-     *
1151
-     * @param string $signedMessage
1152
-     * @param string $pk
1153
-     * @return string
1154
-     */
1155
-    public static function sign_open($signedMessage, $pk)
1156
-    {
1157
-        return ParagonIE_Sodium_Core32_Ed25519::sign_open($signedMessage, $pk);
1158
-    }
1159
-
1160
-    /**
1161
-     * Verify a detached signature of a given message and public key.
1162
-     *
1163
-     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1164
-     *
1165
-     * @param string $signature
1166
-     * @param string $message
1167
-     * @param string $pk
1168
-     * @return bool
1169
-     */
1170
-    public static function sign_verify_detached($signature, $message, $pk)
1171
-    {
1172
-        return ParagonIE_Sodium_Core32_Ed25519::verify_detached($signature, $message, $pk);
1173
-    }
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 Error
69
+	 */
70
+	public static function aead_chacha20poly1305_decrypt(
71
+		$message = '',
72
+		$ad = '',
73
+		$nonce = '',
74
+		$key = ''
75
+	) {
76
+		/** @var int $len - Length of message (ciphertext + MAC) */
77
+		$len = ParagonIE_Sodium_Core32_Util::strlen($message);
78
+
79
+		/** @var int  $clen - Length of ciphertext */
80
+		$clen = $len - self::aead_chacha20poly1305_ABYTES;
81
+
82
+		/** @var int $adlen - Length of associated data */
83
+		$adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
84
+
85
+		/** @var string $mac - Message authentication code */
86
+		$mac = ParagonIE_Sodium_Core32_Util::substr(
87
+			$message,
88
+			$clen,
89
+			self::aead_chacha20poly1305_ABYTES
90
+		);
91
+
92
+		/** @var string $ciphertext - The encrypted message (sans MAC) */
93
+		$ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 0, $clen);
94
+
95
+		/** @var string The first block of the chacha20 keystream, used as a poly1305 key */
96
+		$block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
97
+			32,
98
+			$nonce,
99
+			$key
100
+		);
101
+
102
+		/* Recalculate the Poly1305 authentication tag (MAC): */
103
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
104
+		try {
105
+			ParagonIE_Sodium_Compat::memzero($block0);
106
+		} catch (Error $ex) {
107
+			$block0 = null;
108
+		}
109
+		$state->update($ad);
110
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
111
+		$state->update($ciphertext);
112
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
113
+		$computed_mac = $state->finish();
114
+
115
+		/* Compare the given MAC with the recalculated MAC: */
116
+		if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) {
117
+			throw new Error('Invalid MAC');
118
+		}
119
+
120
+		// Here, we know that the MAC is valid, so we decrypt and return the plaintext
121
+		return ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
122
+			$ciphertext,
123
+			$nonce,
124
+			$key,
125
+			ParagonIE_Sodium_Core32_Util::store64_le(1)
126
+		);
127
+	}
128
+
129
+	/**
130
+	 * AEAD Encryption with ChaCha20-Poly1305
131
+	 *
132
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
133
+	 *
134
+	 * @param string $message
135
+	 * @param string $ad
136
+	 * @param string $nonce
137
+	 * @param string $key
138
+	 * @return string
139
+	 */
140
+	public static function aead_chacha20poly1305_encrypt(
141
+		$message = '',
142
+		$ad = '',
143
+		$nonce = '',
144
+		$key = ''
145
+	) {
146
+		/** @var int $len - Length of the plaintext message */
147
+		$len = ParagonIE_Sodium_Core32_Util::strlen($message);
148
+
149
+		/** @var int $adlen - Length of the associated data */
150
+		$adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
151
+
152
+		/** @var string The first block of the chacha20 keystream, used as a poly1305 key */
153
+		$block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
154
+			32,
155
+			$nonce,
156
+			$key
157
+		);
158
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
159
+		try {
160
+			ParagonIE_Sodium_Compat::memzero($block0);
161
+		} catch (Error $ex) {
162
+			$block0 = null;
163
+		}
164
+
165
+		/** @var string $ciphertext - Raw encrypted data */
166
+		$ciphertext = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
167
+			$message,
168
+			$nonce,
169
+			$key,
170
+			ParagonIE_Sodium_Core32_Util::store64_le(1)
171
+		);
172
+
173
+		$state->update($ad);
174
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
175
+		$state->update($ciphertext);
176
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
177
+		return $ciphertext . $state->finish();
178
+	}
179
+
180
+	/**
181
+	 * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
182
+	 *
183
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
184
+	 *
185
+	 * @param string $message
186
+	 * @param string $ad
187
+	 * @param string $nonce
188
+	 * @param string $key
189
+	 * @return string
190
+	 * @throws Error
191
+	 */
192
+	public static function aead_chacha20poly1305_ietf_decrypt(
193
+		$message = '',
194
+		$ad = '',
195
+		$nonce = '',
196
+		$key = ''
197
+	) {
198
+		/** @var int $adlen - Length of associated data */
199
+		$adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
200
+
201
+		/** @var int $len - Length of message (ciphertext + MAC) */
202
+		$len = ParagonIE_Sodium_Core32_Util::strlen($message);
203
+
204
+		/** @var int  $clen - Length of ciphertext */
205
+		$clen = $len - self::aead_chacha20poly1305_IETF_ABYTES;
206
+
207
+		/** @var string The first block of the chacha20 keystream, used as a poly1305 key */
208
+		$block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
209
+			32,
210
+			$nonce,
211
+			$key
212
+		);
213
+
214
+		/** @var string $mac - Message authentication code */
215
+		$mac = ParagonIE_Sodium_Core32_Util::substr(
216
+			$message,
217
+			$len - self::aead_chacha20poly1305_IETF_ABYTES,
218
+			self::aead_chacha20poly1305_IETF_ABYTES
219
+		);
220
+
221
+		/** @var string $ciphertext - The encrypted message (sans MAC) */
222
+		$ciphertext = ParagonIE_Sodium_Core32_Util::substr(
223
+			$message,
224
+			0,
225
+			$len - self::aead_chacha20poly1305_IETF_ABYTES
226
+		);
227
+
228
+		/* Recalculate the Poly1305 authentication tag (MAC): */
229
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
230
+		try {
231
+			ParagonIE_Sodium_Compat::memzero($block0);
232
+		} catch (Error $ex) {
233
+			$block0 = null;
234
+		}
235
+		$state->update($ad);
236
+		$state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
237
+		$state->update($ciphertext);
238
+		$state->update(str_repeat("\x00", (0x10 - $clen) & 0xf));
239
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
240
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
241
+		$computed_mac = $state->finish();
242
+
243
+		/* Compare the given MAC with the recalculated MAC: */
244
+		if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) {
245
+			throw new Error('Invalid MAC');
246
+		}
247
+
248
+		// Here, we know that the MAC is valid, so we decrypt and return the plaintext
249
+		return ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
250
+			$ciphertext,
251
+			$nonce,
252
+			$key,
253
+			ParagonIE_Sodium_Core32_Util::store64_le(1)
254
+		);
255
+	}
256
+
257
+	/**
258
+	 * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
259
+	 *
260
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
261
+	 *
262
+	 * @param string $message
263
+	 * @param string $ad
264
+	 * @param string $nonce
265
+	 * @param string $key
266
+	 * @return string
267
+	 */
268
+	public static function aead_chacha20poly1305_ietf_encrypt(
269
+		$message = '',
270
+		$ad = '',
271
+		$nonce = '',
272
+		$key = ''
273
+	) {
274
+		/** @var int $len - Length of the plaintext message */
275
+		$len = ParagonIE_Sodium_Core32_Util::strlen($message);
276
+
277
+		/** @var int $adlen - Length of the associated data */
278
+		$adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);
279
+
280
+		/** @var string The first block of the chacha20 keystream, used as a poly1305 key */
281
+		$block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
282
+			32,
283
+			$nonce,
284
+			$key
285
+		);
286
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
287
+		try {
288
+			ParagonIE_Sodium_Compat::memzero($block0);
289
+		} catch (Error $ex) {
290
+			$block0 = null;
291
+		}
292
+
293
+		/** @var string $ciphertext - Raw encrypted data */
294
+		$ciphertext = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
295
+			$message,
296
+			$nonce,
297
+			$key,
298
+			ParagonIE_Sodium_Core32_Util::store64_le(1)
299
+		);
300
+
301
+		$state->update($ad);
302
+		$state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
303
+		$state->update($ciphertext);
304
+		$state->update(str_repeat("\x00", ((0x10 - $len) & 0xf)));
305
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
306
+		$state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
307
+		return $ciphertext . $state->finish();
308
+	}
309
+
310
+	/**
311
+	 * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
312
+	 *
313
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
314
+	 *
315
+	 * @param string $message
316
+	 * @param string $ad
317
+	 * @param string $nonce
318
+	 * @param string $key
319
+	 * @return string
320
+	 * @throws Error
321
+	 */
322
+	public static function aead_xchacha20poly1305_ietf_decrypt(
323
+		$message = '',
324
+		$ad = '',
325
+		$nonce = '',
326
+		$key = ''
327
+	) {
328
+		$subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
329
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
330
+			$key
331
+		);
332
+		$nonceLast = "\x00\x00\x00\x00" .
333
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);
334
+
335
+		return self::aead_chacha20poly1305_ietf_decrypt($message, $ad, $nonceLast, $subkey);
336
+	}
337
+
338
+	/**
339
+	 * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
340
+	 *
341
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
342
+	 *
343
+	 * @param string $message
344
+	 * @param string $ad
345
+	 * @param string $nonce
346
+	 * @param string $key
347
+	 * @return string
348
+	 */
349
+	public static function aead_xchacha20poly1305_ietf_encrypt(
350
+		$message = '',
351
+		$ad = '',
352
+		$nonce = '',
353
+		$key = ''
354
+	) {
355
+		$subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
356
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
357
+			$key
358
+		);
359
+		$nonceLast = "\x00\x00\x00\x00" .
360
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);
361
+
362
+		return self::aead_chacha20poly1305_ietf_encrypt($message, $ad, $nonceLast, $subkey);
363
+	}
364
+
365
+	/**
366
+	 * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
367
+	 *
368
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
369
+	 *
370
+	 * @param string $message
371
+	 * @param string $key
372
+	 * @return string
373
+	 */
374
+	public static function auth($message, $key)
375
+	{
376
+		return ParagonIE_Sodium_Core32_Util::substr(
377
+			hash_hmac('sha512', $message, $key, true),
378
+			0,
379
+			32
380
+		);
381
+	}
382
+
383
+	/**
384
+	 * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
385
+	 *
386
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
387
+	 *
388
+	 * @param string $mac
389
+	 * @param string $message
390
+	 * @param string $key
391
+	 * @return bool
392
+	 */
393
+	public static function auth_verify($mac, $message, $key)
394
+	{
395
+		return ParagonIE_Sodium_Core32_Util::hashEquals(
396
+			$mac,
397
+			self::auth($message, $key)
398
+		);
399
+	}
400
+
401
+	/**
402
+	 * X25519 key exchange followed by XSalsa20Poly1305 symmetric encryption
403
+	 *
404
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
405
+	 *
406
+	 * @param string $plaintext
407
+	 * @param string $nonce
408
+	 * @param string $keypair
409
+	 * @return string
410
+	 */
411
+	public static function box($plaintext, $nonce, $keypair)
412
+	{
413
+		$c = self::secretbox(
414
+			$plaintext,
415
+			$nonce,
416
+			self::box_beforenm(
417
+				self::box_secretkey($keypair),
418
+				self::box_publickey($keypair)
419
+			)
420
+		);
421
+		return $c;
422
+	}
423
+
424
+	/**
425
+	 * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair.
426
+	 *
427
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
428
+	 *
429
+	 * @param string $message
430
+	 * @param string $publicKey
431
+	 * @return string
432
+	 */
433
+	public static function box_seal($message, $publicKey)
434
+	{
435
+		/** @var string $ephemeralKeypair */
436
+		$ephemeralKeypair = self::box_keypair();
437
+
438
+		/** @var string $ephemeralSK */
439
+		$ephemeralSK = self::box_secretkey($ephemeralKeypair);
440
+
441
+		/** @var string $ephemeralPK */
442
+		$ephemeralPK = self::box_publickey($ephemeralKeypair);
443
+
444
+		/** @var string $nonce */
445
+		$nonce = self::generichash(
446
+			$ephemeralPK . $publicKey,
447
+			'',
448
+			24
449
+		);
450
+
451
+		/** @var string $keypair - The combined keypair used in crypto_box() */
452
+		$keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);
453
+
454
+		/** @var string $ciphertext Ciphertext + MAC from crypto_box */
455
+		$ciphertext = self::box($message, $nonce, $keypair);
456
+		try {
457
+			ParagonIE_Sodium_Compat::memzero($ephemeralKeypair);
458
+			ParagonIE_Sodium_Compat::memzero($ephemeralSK);
459
+			ParagonIE_Sodium_Compat::memzero($nonce);
460
+		} catch (Error $ex) {
461
+			$ephemeralKeypair = null;
462
+			$ephemeralSK = null;
463
+			$nonce = null;
464
+		}
465
+		return $ephemeralPK . $ciphertext;
466
+	}
467
+
468
+	/**
469
+	 * Opens a message encrypted via box_seal().
470
+	 *
471
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
472
+	 *
473
+	 * @param string $message
474
+	 * @param string $keypair
475
+	 * @return string
476
+	 */
477
+	public static function box_seal_open($message, $keypair)
478
+	{
479
+		/** @var string $ephemeralPK */
480
+		$ephemeralPK = ParagonIE_Sodium_Core32_Util::substr($message, 0, 32);
481
+
482
+		/** @var string $ciphertext (ciphertext + MAC) */
483
+		$ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 32);
484
+
485
+		/** @var string $secretKey */
486
+		$secretKey = self::box_secretkey($keypair);
487
+
488
+		/** @var string $publicKey */
489
+		$publicKey = self::box_publickey($keypair);
490
+
491
+		/** @var string $nonce */
492
+		$nonce = self::generichash(
493
+			$ephemeralPK . $publicKey,
494
+			'',
495
+			24
496
+		);
497
+
498
+		/** @var string $keypair */
499
+		$keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);
500
+
501
+		/** @var string $m */
502
+		$m = self::box_open($ciphertext, $nonce, $keypair);
503
+		try {
504
+			ParagonIE_Sodium_Compat::memzero($secretKey);
505
+			ParagonIE_Sodium_Compat::memzero($ephemeralPK);
506
+			ParagonIE_Sodium_Compat::memzero($nonce);
507
+		} catch (Error $ex) {
508
+			$secretKey = null;
509
+			$ephemeralPK = null;
510
+			$nonce = null;
511
+		}
512
+		return $m;
513
+	}
514
+
515
+	/**
516
+	 * Used by crypto_box() to get the crypto_secretbox() key.
517
+	 *
518
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
519
+	 *
520
+	 * @param string $sk
521
+	 * @param string $pk
522
+	 * @return string
523
+	 */
524
+	public static function box_beforenm($sk, $pk)
525
+	{
526
+		return ParagonIE_Sodium_Core32_HSalsa20::hsalsa20(
527
+			str_repeat("\x00", 16),
528
+			self::scalarmult($sk, $pk)
529
+		);
530
+	}
531
+
532
+	/**
533
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
534
+	 *
535
+	 * @return string
536
+	 */
537
+	public static function box_keypair()
538
+	{
539
+		$sKey = random_bytes(32);
540
+		$pKey = self::scalarmult_base($sKey);
541
+		return $sKey . $pKey;
542
+	}
543
+
544
+	/**
545
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
546
+	 *
547
+	 * @param string $sKey
548
+	 * @param string $pKey
549
+	 * @return string
550
+	 */
551
+	public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey)
552
+	{
553
+		return ParagonIE_Sodium_Core32_Util::substr($sKey, 0, 32) .
554
+			ParagonIE_Sodium_Core32_Util::substr($pKey, 0, 32);
555
+	}
556
+
557
+	/**
558
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
559
+	 *
560
+	 * @param string $keypair
561
+	 * @return string
562
+	 * @throws RangeException
563
+	 */
564
+	public static function box_secretkey($keypair)
565
+	{
566
+		if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== 64) {
567
+			throw new RangeException('Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.');
568
+		}
569
+		return ParagonIE_Sodium_Core32_Util::substr($keypair, 0, 32);
570
+	}
571
+
572
+	/**
573
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
574
+	 *
575
+	 * @param string $keypair
576
+	 * @return string
577
+	 * @throws RangeException
578
+	 */
579
+	public static function box_publickey($keypair)
580
+	{
581
+		if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
582
+			throw new RangeException('Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.');
583
+		}
584
+		return ParagonIE_Sodium_Core32_Util::substr($keypair, 32, 32);
585
+	}
586
+
587
+	/**
588
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
589
+	 *
590
+	 * @param string $sKey
591
+	 * @return string
592
+	 * @throws RangeException
593
+	 */
594
+	public static function box_publickey_from_secretkey($sKey)
595
+	{
596
+		if (ParagonIE_Sodium_Core32_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) {
597
+			throw new RangeException('Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.');
598
+		}
599
+		return self::scalarmult_base($sKey);
600
+	}
601
+
602
+	/**
603
+	 * Decrypt a message encrypted with box().
604
+	 *
605
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
606
+	 *
607
+	 * @param string $ciphertext
608
+	 * @param string $nonce
609
+	 * @param string $nonce
610
+	 * @param string $keypair
611
+	 * @return string
612
+	 */
613
+	public static function box_open($ciphertext, $nonce, $keypair)
614
+	{
615
+		return self::secretbox_open(
616
+			$ciphertext,
617
+			$nonce,
618
+			self::box_beforenm(
619
+				self::box_secretkey($keypair),
620
+				self::box_publickey($keypair)
621
+			)
622
+		);
623
+	}
624
+
625
+	/**
626
+	 * Calculate a BLAKE2b hash.
627
+	 *
628
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
629
+	 *
630
+	 * @param string $message
631
+	 * @param string|null $key
632
+	 * @param int $outlen
633
+	 * @return string
634
+	 * @throws RangeException
635
+	 */
636
+	public static function generichash($message, $key = '', $outlen = 32)
637
+	{
638
+		// This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
639
+		ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
640
+
641
+		$k = null;
642
+		if (!empty($key)) {
643
+			/** @var SplFixedArray $k */
644
+			$k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
645
+			if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
646
+				throw new RangeException('Invalid key size');
647
+			}
648
+		}
649
+
650
+		/** @var SplFixedArray $in */
651
+		$in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);
652
+
653
+		/** @var SplFixedArray $ctx */
654
+		$ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outlen);
655
+		ParagonIE_Sodium_Core32_BLAKE2b::update($ctx, $in, $in->count());
656
+
657
+		/** @var SplFixedArray $out */
658
+		$out = new SplFixedArray($outlen);
659
+		$out = ParagonIE_Sodium_Core32_BLAKE2b::finish($ctx, $out);
660
+
661
+		/** @var array<int, int> */
662
+		$outArray = $out->toArray();
663
+		return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
664
+	}
665
+
666
+	/**
667
+	 * Finalize a BLAKE2b hashing context, returning the hash.
668
+	 *
669
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
670
+	 *
671
+	 * @param string $ctx
672
+	 * @param int $outlen
673
+	 * @return string
674
+	 * @throws TypeError
675
+	 */
676
+	public static function generichash_final($ctx, $outlen = 32)
677
+	{
678
+		if (!is_string($ctx)) {
679
+			throw new TypeError('Context must be a string');
680
+		}
681
+		$out = new SplFixedArray($outlen);
682
+
683
+		/** @var SplFixedArray $context */
684
+		$context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);
685
+
686
+		/** @var SplFixedArray $out */
687
+		$out = ParagonIE_Sodium_Core32_BLAKE2b::finish($context, $out);
688
+
689
+		/** @var array<int, int> */
690
+		$outArray = $out->toArray();
691
+		return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
692
+	}
693
+
694
+	/**
695
+	 * Initialize a hashing context for BLAKE2b.
696
+	 *
697
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
698
+	 *
699
+	 * @param string $key
700
+	 * @param int $outputLength
701
+	 * @return string
702
+	 * @throws RangeException
703
+	 */
704
+	public static function generichash_init($key = '', $outputLength = 32)
705
+	{
706
+		// This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
707
+		ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
708
+
709
+		$k = null;
710
+		if (!empty($key)) {
711
+			$k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
712
+			if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
713
+				throw new RangeException('Invalid key size');
714
+			}
715
+		}
716
+
717
+		/** @var SplFixedArray $ctx */
718
+		$ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength);
719
+
720
+		return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
721
+	}
722
+
723
+	/**
724
+	 * Update a hashing context for BLAKE2b with $message
725
+	 *
726
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
727
+	 *
728
+	 * @param string $ctx
729
+	 * @param string $message
730
+	 * @return string
731
+	 */
732
+	public static function generichash_update($ctx, $message)
733
+	{
734
+		// This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
735
+		ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
736
+
737
+		/** @var SplFixedArray $context */
738
+		$context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);
739
+
740
+		/** @var SplFixedArray $in */
741
+		$in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);
742
+
743
+		ParagonIE_Sodium_Core32_BLAKE2b::update($context, $in, $in->count());
744
+
745
+		return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($context);
746
+	}
747
+
748
+	/**
749
+	 * Libsodium's crypto_kx().
750
+	 *
751
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
752
+	 *
753
+	 * @param string $my_sk
754
+	 * @param string $their_pk
755
+	 * @param string $client_pk
756
+	 * @param string $server_pk
757
+	 * @return string
758
+	 */
759
+	public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk)
760
+	{
761
+		return self::generichash(
762
+			self::scalarmult($my_sk, $their_pk) .
763
+			$client_pk .
764
+			$server_pk
765
+		);
766
+	}
767
+
768
+	/**
769
+	 * ECDH over Curve25519
770
+	 *
771
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
772
+	 *
773
+	 * @param string $sKey
774
+	 * @param string $pKey
775
+	 * @return string
776
+	 *
777
+	 * @throws Error
778
+	 */
779
+	public static function scalarmult($sKey, $pKey)
780
+	{
781
+		$q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey);
782
+		self::scalarmult_throw_if_zero($q);
783
+		return $q;
784
+	}
785
+
786
+	/**
787
+	 * ECDH over Curve25519, using the basepoint.
788
+	 * Used to get a secret key from a public key.
789
+	 *
790
+	 * @param string $secret
791
+	 * @return string
792
+	 *
793
+	 * @throws Error
794
+	 */
795
+	public static function scalarmult_base($secret)
796
+	{
797
+		$q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
798
+		self::scalarmult_throw_if_zero($q);
799
+		return $q;
800
+	}
801
+
802
+	/**
803
+	 * This throws an Error if a zero public key was passed to the function.
804
+	 *
805
+	 * @param string $q
806
+	 * @return void
807
+	 * @throws Error
808
+	 */
809
+	protected static function scalarmult_throw_if_zero($q)
810
+	{
811
+		$d = 0;
812
+		for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
813
+			$d |= ParagonIE_Sodium_Core32_Util::chrToInt($q[$i]);
814
+		}
815
+
816
+		/* branch-free variant of === 0 */
817
+		if (-(1 & (($d - 1) >> 8))) {
818
+			throw new Error('Zero public key is not allowed');
819
+		}
820
+	}
821
+
822
+	/**
823
+	 * XSalsa20-Poly1305 authenticated symmetric-key encryption.
824
+	 *
825
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
826
+	 *
827
+	 * @param string $plaintext
828
+	 * @param string $nonce
829
+	 * @param string $key
830
+	 * @return string
831
+	 */
832
+	public static function secretbox($plaintext, $nonce, $key)
833
+	{
834
+		/** @var string $subkey */
835
+		$subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);
836
+
837
+		/** @var string $block0 */
838
+		$block0 = str_repeat("\x00", 32);
839
+
840
+		/** @var int $mlen - Length of the plaintext message */
841
+		$mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
842
+		$mlen0 = $mlen;
843
+		if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
844
+			$mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
845
+		}
846
+		$block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0);
847
+
848
+		/** @var string $block0 */
849
+		$block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor(
850
+			$block0,
851
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
852
+			$subkey
853
+		);
854
+
855
+		/** @var string $c */
856
+		$c = ParagonIE_Sodium_Core32_Util::substr(
857
+			$block0,
858
+			self::secretbox_xsalsa20poly1305_ZEROBYTES
859
+		);
860
+		if ($mlen > $mlen0) {
861
+			$c .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
862
+				ParagonIE_Sodium_Core32_Util::substr(
863
+					$plaintext,
864
+					self::secretbox_xsalsa20poly1305_ZEROBYTES
865
+				),
866
+				ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
867
+				1,
868
+				$subkey
869
+			);
870
+		}
871
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State(
872
+			ParagonIE_Sodium_Core32_Util::substr(
873
+				$block0,
874
+				0,
875
+				self::onetimeauth_poly1305_KEYBYTES
876
+			)
877
+		);
878
+		try {
879
+			ParagonIE_Sodium_Compat::memzero($block0);
880
+			ParagonIE_Sodium_Compat::memzero($subkey);
881
+		} catch (Error $ex) {
882
+			$block0 = null;
883
+			$subkey = null;
884
+		}
885
+
886
+		$state->update($c);
887
+
888
+		/** @var string $c - MAC || ciphertext */
889
+		$c = $state->finish() . $c;
890
+		unset($state);
891
+
892
+		return $c;
893
+	}
894
+
895
+	/**
896
+	 * Decrypt a ciphertext generated via secretbox().
897
+	 *
898
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
899
+	 *
900
+	 * @param string $ciphertext
901
+	 * @param string $nonce
902
+	 * @param string $key
903
+	 * @return string
904
+	 * @throws Error
905
+	 */
906
+	public static function secretbox_open($ciphertext, $nonce, $key)
907
+	{
908
+		/** @var string $mac */
909
+		$mac = ParagonIE_Sodium_Core32_Util::substr(
910
+			$ciphertext,
911
+			0,
912
+			self::secretbox_xsalsa20poly1305_MACBYTES
913
+		);
914
+
915
+		/** @var string $c */
916
+		$c = ParagonIE_Sodium_Core32_Util::substr(
917
+			$ciphertext,
918
+			self::secretbox_xsalsa20poly1305_MACBYTES
919
+		);
920
+
921
+		/** @var int $clen */
922
+		$clen = ParagonIE_Sodium_Core32_Util::strlen($c);
923
+
924
+		/** @var string $subkey */
925
+		$subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);
926
+
927
+		/** @var string $block0 */
928
+		$block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20(
929
+			64,
930
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
931
+			$subkey
932
+		);
933
+		$verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
934
+			$mac,
935
+			$c,
936
+			ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
937
+		);
938
+		if (!$verified) {
939
+			try {
940
+				ParagonIE_Sodium_Compat::memzero($subkey);
941
+			} catch (Error $ex) {
942
+				$subkey = null;
943
+			}
944
+			throw new Error('Invalid MAC');
945
+		}
946
+
947
+		/** @var string $m - Decrypted message */
948
+		$m = ParagonIE_Sodium_Core32_Util::xorStrings(
949
+			ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES),
950
+			ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES)
951
+		);
952
+		if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
953
+			// We had more than 1 block, so let's continue to decrypt the rest.
954
+			$m .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
955
+				ParagonIE_Sodium_Core32_Util::substr(
956
+					$c,
957
+					self::secretbox_xsalsa20poly1305_ZEROBYTES
958
+				),
959
+				ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
960
+				1,
961
+				$subkey
962
+			);
963
+		}
964
+		return $m;
965
+	}
966
+
967
+	/**
968
+	 * XChaCha20-Poly1305 authenticated symmetric-key encryption.
969
+	 *
970
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
971
+	 *
972
+	 * @param string $plaintext
973
+	 * @param string $nonce
974
+	 * @param string $key
975
+	 * @return string
976
+	 */
977
+	public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key)
978
+	{
979
+		/** @var string $subkey */
980
+		$subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
981
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
982
+			$key
983
+		);
984
+		$nonceLast = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);
985
+
986
+		/** @var string $block0 */
987
+		$block0 = str_repeat("\x00", 32);
988
+
989
+		/** @var int $mlen - Length of the plaintext message */
990
+		$mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
991
+		$mlen0 = $mlen;
992
+		if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) {
993
+			$mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES;
994
+		}
995
+		$block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0);
996
+
997
+		/** @var string $block0 */
998
+		$block0 = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
999
+			$block0,
1000
+			$nonceLast,
1001
+			$subkey
1002
+		);
1003
+
1004
+		/** @var string $c */
1005
+		$c = ParagonIE_Sodium_Core32_Util::substr(
1006
+			$block0,
1007
+			self::secretbox_xchacha20poly1305_ZEROBYTES
1008
+		);
1009
+		if ($mlen > $mlen0) {
1010
+			$c .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
1011
+				ParagonIE_Sodium_Core32_Util::substr(
1012
+					$plaintext,
1013
+					self::secretbox_xchacha20poly1305_ZEROBYTES
1014
+				),
1015
+				$nonceLast,
1016
+				$subkey,
1017
+				ParagonIE_Sodium_Core32_Util::store64_le(1)
1018
+			);
1019
+		}
1020
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State(
1021
+			ParagonIE_Sodium_Core32_Util::substr(
1022
+				$block0,
1023
+				0,
1024
+				self::onetimeauth_poly1305_KEYBYTES
1025
+			)
1026
+		);
1027
+		try {
1028
+			ParagonIE_Sodium_Compat::memzero($block0);
1029
+			ParagonIE_Sodium_Compat::memzero($subkey);
1030
+		} catch (Error $ex) {
1031
+			$block0 = null;
1032
+			$subkey = null;
1033
+		}
1034
+
1035
+		$state->update($c);
1036
+
1037
+		/** @var string $c - MAC || ciphertext */
1038
+		$c = $state->finish() . $c;
1039
+		unset($state);
1040
+
1041
+		return $c;
1042
+	}
1043
+
1044
+	/**
1045
+	 * Decrypt a ciphertext generated via secretbox_xchacha20poly1305().
1046
+	 *
1047
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1048
+	 *
1049
+	 * @param string $ciphertext
1050
+	 * @param string $nonce
1051
+	 * @param string $key
1052
+	 * @return string
1053
+	 * @throws Error
1054
+	 */
1055
+	public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key)
1056
+	{
1057
+		/** @var string $mac */
1058
+		$mac = ParagonIE_Sodium_Core32_Util::substr(
1059
+			$ciphertext,
1060
+			0,
1061
+			self::secretbox_xchacha20poly1305_MACBYTES
1062
+		);
1063
+
1064
+		/** @var string $c */
1065
+		$c = ParagonIE_Sodium_Core32_Util::substr(
1066
+			$ciphertext,
1067
+			self::secretbox_xchacha20poly1305_MACBYTES
1068
+		);
1069
+
1070
+		/** @var int $clen */
1071
+		$clen = ParagonIE_Sodium_Core32_Util::strlen($c);
1072
+
1073
+		/** @var string $subkey */
1074
+		$subkey = ParagonIE_Sodium_Core32_HChaCha20::hchacha20($nonce, $key);
1075
+
1076
+		/** @var string $block0 */
1077
+		$block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
1078
+			64,
1079
+			ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
1080
+			$subkey
1081
+		);
1082
+		$verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
1083
+			$mac,
1084
+			$c,
1085
+			ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
1086
+		);
1087
+
1088
+		if (!$verified) {
1089
+			try {
1090
+				ParagonIE_Sodium_Compat::memzero($subkey);
1091
+			} catch (Error $ex) {
1092
+				$subkey = null;
1093
+			}
1094
+			throw new Error('Invalid MAC');
1095
+		}
1096
+
1097
+		/** @var string $m - Decrypted message */
1098
+		$m = ParagonIE_Sodium_Core32_Util::xorStrings(
1099
+			ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES),
1100
+			ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xchacha20poly1305_ZEROBYTES)
1101
+		);
1102
+
1103
+		if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) {
1104
+			// We had more than 1 block, so let's continue to decrypt the rest.
1105
+			$m .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
1106
+				ParagonIE_Sodium_Core32_Util::substr(
1107
+					$c,
1108
+					self::secretbox_xchacha20poly1305_ZEROBYTES
1109
+				),
1110
+				ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
1111
+				$subkey,
1112
+				ParagonIE_Sodium_Core32_Util::store64_le(1)
1113
+			);
1114
+		}
1115
+		return $m;
1116
+	}
1117
+
1118
+	/**
1119
+	 * Detached Ed25519 signature.
1120
+	 *
1121
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1122
+	 *
1123
+	 * @param string $message
1124
+	 * @param string $sk
1125
+	 * @return string
1126
+	 */
1127
+	public static function sign_detached($message, $sk)
1128
+	{
1129
+		return ParagonIE_Sodium_Core32_Ed25519::sign_detached($message, $sk);
1130
+	}
1131
+
1132
+	/**
1133
+	 * Attached Ed25519 signature. (Returns a signed message.)
1134
+	 *
1135
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1136
+	 *
1137
+	 * @param string $message
1138
+	 * @param string $sk
1139
+	 * @return string
1140
+	 */
1141
+	public static function sign($message, $sk)
1142
+	{
1143
+		return ParagonIE_Sodium_Core32_Ed25519::sign($message, $sk);
1144
+	}
1145
+
1146
+	/**
1147
+	 * Opens a signed message. If valid, returns the message.
1148
+	 *
1149
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1150
+	 *
1151
+	 * @param string $signedMessage
1152
+	 * @param string $pk
1153
+	 * @return string
1154
+	 */
1155
+	public static function sign_open($signedMessage, $pk)
1156
+	{
1157
+		return ParagonIE_Sodium_Core32_Ed25519::sign_open($signedMessage, $pk);
1158
+	}
1159
+
1160
+	/**
1161
+	 * Verify a detached signature of a given message and public key.
1162
+	 *
1163
+	 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
1164
+	 *
1165
+	 * @param string $signature
1166
+	 * @param string $message
1167
+	 * @param string $pk
1168
+	 * @return bool
1169
+	 */
1170
+	public static function sign_verify_detached($signature, $message, $pk)
1171
+	{
1172
+		return ParagonIE_Sodium_Core32_Ed25519::verify_detached($signature, $message, $pk);
1173
+	}
1174 1174
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/File.php 1 patch
Indentation   +1061 added lines, -1061 removed lines patch added patch discarded remove patch
@@ -1,1080 +1,1080 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_File', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 /**
7 7
  * Class ParagonIE_Sodium_File
8 8
  */
9 9
 class ParagonIE_Sodium_File extends ParagonIE_Sodium_Core_Util
10 10
 {
11
-    /* PHP's default buffer size is 8192 for fread()/fwrite(). */
12
-    const BUFFER_SIZE = 8192;
13
-
14
-    /**
15
-     * Box a file (rather than a string). Uses less memory than
16
-     * ParagonIE_Sodium_Compat::crypto_box(), but produces
17
-     * the same result.
18
-     *
19
-     * @param string $inputFile  Absolute path to a file on the filesystem
20
-     * @param string $outputFile Absolute path to a file on the filesystem
21
-     * @param string $nonce      Number to be used only once
22
-     * @param string $keyPair    ECDH secret key and ECDH public key concatenated
23
-     *
24
-     * @return bool
25
-     * @throws Error
26
-     * @throws TypeError
27
-     */
28
-    public static function box($inputFile, $outputFile, $nonce, $keyPair)
29
-    {
30
-        /* Type checks: */
31
-        if (!is_string($inputFile)) {
32
-            throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
33
-        }
34
-        if (!is_string($outputFile)) {
35
-            throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
36
-        }
37
-        if (!is_string($nonce)) {
38
-            throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
39
-        }
40
-
41
-        /* Input validation: */
42
-        if (!is_string($keyPair)) {
43
-            throw new TypeError('Argument 4 must be a string, ' . gettype($keyPair) . ' given.');
44
-        }
45
-        if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
46
-            throw new TypeError('Argument 3 must be CRYPTO_BOX_NONCEBYTES bytes');
47
-        }
48
-        if (self::strlen($keyPair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
49
-            throw new TypeError('Argument 4 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
50
-        }
51
-
52
-        /** @var int $size */
53
-        $size = filesize($inputFile);
54
-        if (!is_int($size)) {
55
-            throw new Error('Could not obtain the file size');
56
-        }
57
-
58
-        /** @var resource $ifp */
59
-        $ifp = fopen($inputFile, 'rb');
60
-        if (!is_resource($ifp)) {
61
-            throw new Error('Could not open input file for reading');
62
-        }
63
-
64
-        /** @var resource $ofp */
65
-        $ofp = fopen($outputFile, 'wb');
66
-        if (!is_resource($ofp)) {
67
-            fclose($ifp);
68
-            throw new Error('Could not open output file for writing');
69
-        }
70
-
71
-        $res = self::box_encrypt($ifp, $ofp, $size, $nonce, $keyPair);
72
-        fclose($ifp);
73
-        fclose($ofp);
74
-        return $res;
75
-    }
76
-
77
-    /**
78
-     * Open a boxed file (rather than a string). Uses less memory than
79
-     * ParagonIE_Sodium_Compat::crypto_box_open(), but produces
80
-     * the same result.
81
-     *
82
-     * Warning: Does not protect against TOCTOU attacks. You should
83
-     * just load the file into memory and use crypto_box_open() if
84
-     * you are worried about those.
85
-     *
86
-     * @param string $inputFile
87
-     * @param string $outputFile
88
-     * @param string $nonce
89
-     * @param string $keypair
90
-     * @return bool
91
-     * @throws Error
92
-     * @throws TypeError
93
-     */
94
-    public static function box_open($inputFile, $outputFile, $nonce, $keypair)
95
-    {
96
-        /* Type checks: */
97
-        if (!is_string($inputFile)) {
98
-            throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
99
-        }
100
-        if (!is_string($outputFile)) {
101
-            throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
102
-        }
103
-        if (!is_string($nonce)) {
104
-            throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
105
-        }
106
-        if (!is_string($keypair)) {
107
-            throw new TypeError('Argument 4 must be a string, ' . gettype($keypair) . ' given.');
108
-        }
109
-
110
-        /* Input validation: */
111
-        if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
112
-            throw new TypeError('Argument 4 must be CRYPTO_BOX_NONCEBYTES bytes');
113
-        }
114
-        if (self::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
115
-            throw new TypeError('Argument 4 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
116
-        }
117
-
118
-        /** @var int $size */
119
-        $size = filesize($inputFile);
120
-        if (!is_int($size)) {
121
-            throw new Error('Could not obtain the file size');
122
-        }
123
-
124
-        /** @var resource $ifp */
125
-        $ifp = fopen($inputFile, 'rb');
126
-        if (!is_resource($ifp)) {
127
-            throw new Error('Could not open input file for reading');
128
-        }
129
-
130
-        /** @var resource $ofp */
131
-        $ofp = fopen($outputFile, 'wb');
132
-        if (!is_resource($ofp)) {
133
-            fclose($ifp);
134
-            throw new Error('Could not open output file for writing');
135
-        }
136
-
137
-        $res = self::box_decrypt($ifp, $ofp, $size, $nonce, $keypair);
138
-        fclose($ifp);
139
-        fclose($ofp);
140
-        try {
141
-            ParagonIE_Sodium_Compat::memzero($nonce);
142
-            ParagonIE_Sodium_Compat::memzero($ephKeypair);
143
-        } catch (Error $ex) {
144
-            unset($ephKeypair);
145
-        }
146
-        return $res;
147
-    }
148
-
149
-    /**
150
-     * Seal a file (rather than a string). Uses less memory than
151
-     * ParagonIE_Sodium_Compat::crypto_box_seal(), but produces
152
-     * the same result.
153
-     *
154
-     * @param string $inputFile  Absolute path to a file on the filesystem
155
-     * @param string $outputFile Absolute path to a file on the filesystem
156
-     * @param string $publicKey  ECDH public key
157
-     *
158
-     * @return bool
159
-     * @throws Error
160
-     * @throws TypeError
161
-     */
162
-    public static function box_seal($inputFile, $outputFile, $publicKey)
163
-    {
164
-        /* Type checks: */
165
-        if (!is_string($inputFile)) {
166
-            throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
167
-        }
168
-        if (!is_string($outputFile)) {
169
-            throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
170
-        }
171
-        if (!is_string($publicKey)) {
172
-            throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.');
173
-        }
174
-
175
-        /* Input validation: */
176
-        if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
177
-            throw new TypeError('Argument 3 must be CRYPTO_BOX_PUBLICKEYBYTES bytes');
178
-        }
179
-
180
-        /** @var int $size */
181
-        $size = filesize($inputFile);
182
-        if (!is_int($size)) {
183
-            throw new Error('Could not obtain the file size');
184
-        }
185
-
186
-        /** @var resource $ifp */
187
-        $ifp = fopen($inputFile, 'rb');
188
-        if (!is_resource($ifp)) {
189
-            throw new Error('Could not open input file for reading');
190
-        }
191
-
192
-        /** @var resource $ofp */
193
-        $ofp = fopen($outputFile, 'wb');
194
-        if (!is_resource($ofp)) {
195
-            fclose($ifp);
196
-            throw new Error('Could not open output file for writing');
197
-        }
198
-
199
-        /** @var string $ephKeypair */
200
-        $ephKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair();
201
-
202
-        /** @var string $msgKeypair */
203
-        $msgKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
204
-            ParagonIE_Sodium_Compat::crypto_box_secretkey($ephKeypair),
205
-            $publicKey
206
-        );
207
-
208
-        /** @var string $ephemeralPK */
209
-        $ephemeralPK = ParagonIE_Sodium_Compat::crypto_box_publickey($ephKeypair);
210
-
211
-        /** @var string $nonce */
212
-        $nonce = ParagonIE_Sodium_Compat::crypto_generichash(
213
-            $ephemeralPK . $publicKey,
214
-            '',
215
-            24
216
-        );
217
-
218
-        /** @var int $firstWrite */
219
-        $firstWrite = fwrite(
220
-            $ofp,
221
-            $ephemeralPK,
222
-            ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES
223
-        );
224
-        if (!is_int($firstWrite)) {
225
-            fclose($ifp);
226
-            fclose($ofp);
227
-            ParagonIE_Sodium_Compat::memzero($ephKeypair);
228
-            throw new Error('Could not write to output file');
229
-        }
230
-        if ($firstWrite !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
231
-            ParagonIE_Sodium_Compat::memzero($ephKeypair);
232
-            fclose($ifp);
233
-            fclose($ofp);
234
-            throw new Error('Error writing public key to output file');
235
-        }
236
-
237
-        $res = self::box_encrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
238
-        fclose($ifp);
239
-        fclose($ofp);
240
-        try {
241
-            ParagonIE_Sodium_Compat::memzero($nonce);
242
-            ParagonIE_Sodium_Compat::memzero($ephKeypair);
243
-        } catch (Error $ex) {
244
-            unset($ephKeypair);
245
-        }
246
-        return $res;
247
-    }
248
-
249
-    /**
250
-     * Open a sealed file (rather than a string). Uses less memory than
251
-     * ParagonIE_Sodium_Compat::crypto_box_seal_open(), but produces
252
-     * the same result.
253
-     *
254
-     * Warning: Does not protect against TOCTOU attacks. You should
255
-     * just load the file into memory and use crypto_box_seal_open() if
256
-     * you are worried about those.
257
-     *
258
-     * @param string $inputFile
259
-     * @param string $outputFile
260
-     * @param string $ecdhKeypair
261
-     * @return bool
262
-     * @throws Error
263
-     * @throws TypeError
264
-     */
265
-    public static function box_seal_open($inputFile, $outputFile, $ecdhKeypair)
266
-    {
267
-        /* Type checks: */
268
-        if (!is_string($inputFile)) {
269
-            throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
270
-        }
271
-        if (!is_string($outputFile)) {
272
-            throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
273
-        }
274
-        if (!is_string($ecdhKeypair)) {
275
-            throw new TypeError('Argument 3 must be a string, ' . gettype($ecdhKeypair) . ' given.');
276
-        }
277
-
278
-        /* Input validation: */
279
-        if (self::strlen($ecdhKeypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
280
-            throw new TypeError('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
281
-        }
282
-
283
-        $publicKey = ParagonIE_Sodium_Compat::crypto_box_publickey($ecdhKeypair);
284
-
285
-        /** @var int $size */
286
-        $size = filesize($inputFile);
287
-        if (!is_int($size)) {
288
-            throw new Error('Could not obtain the file size');
289
-        }
290
-
291
-        /** @var resource $ifp */
292
-        $ifp = fopen($inputFile, 'rb');
293
-        if (!is_resource($ifp)) {
294
-            throw new Error('Could not open input file for reading');
295
-        }
296
-
297
-        /** @var resource $ofp */
298
-        $ofp = fopen($outputFile, 'wb');
299
-        if (!is_resource($ofp)) {
300
-            fclose($ifp);
301
-            throw new Error('Could not open output file for writing');
302
-        }
303
-
304
-        $ephemeralPK = fread($ifp, ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES);
305
-        if (!is_string($ephemeralPK)) {
306
-            throw new Error('Could not read input file');
307
-        }
308
-        if (self::strlen($ephemeralPK) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
309
-            fclose($ifp);
310
-            fclose($ofp);
311
-            throw new Error('Could not read public key from sealed file');
312
-        }
313
-
314
-        $nonce = ParagonIE_Sodium_Compat::crypto_generichash(
315
-            $ephemeralPK . $publicKey,
316
-            '',
317
-            24
318
-        );
319
-        $msgKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
320
-            ParagonIE_Sodium_Compat::crypto_box_secretkey($ecdhKeypair),
321
-            $ephemeralPK
322
-        );
323
-
324
-        $res = self::box_decrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
325
-        fclose($ifp);
326
-        fclose($ofp);
327
-        try {
328
-            ParagonIE_Sodium_Compat::memzero($nonce);
329
-            ParagonIE_Sodium_Compat::memzero($ephKeypair);
330
-        } catch (Error $ex) {
331
-            unset($ephKeypair);
332
-        }
333
-        return $res;
334
-    }
335
-
336
-    /**
337
-     * Calculate the BLAKE2b hash of a file.
338
-     *
339
-     * @param string      $filePath     Absolute path to a file on the filesystem
340
-     * @param string|null $key          BLAKE2b key
341
-     * @param int         $outputLength Length of hash output
342
-     *
343
-     * @return string                   BLAKE2b hash
344
-     * @throws Error
345
-     * @throws TypeError
346
-     * @psalm-suppress FailedTypeResolution
347
-     */
348
-    public static function generichash($filePath, $key = '', $outputLength = 32)
349
-    {
350
-        /* Type checks: */
351
-        if (!is_string($filePath)) {
352
-            throw new TypeError('Argument 1 must be a string, ' . gettype($filePath) . ' given.');
353
-        }
354
-        if (!is_string($key)) {
355
-            if (is_null($key)) {
356
-                $key = '';
357
-            } else {
358
-                throw new TypeError('Argument 2 must be a string, ' . gettype($key) . ' given.');
359
-            }
360
-        }
361
-        if (!is_int($outputLength)) {
362
-            if (!is_numeric($outputLength)) {
363
-                throw new TypeError('Argument 3 must be an integer, ' . gettype($outputLength) . ' given.');
364
-            }
365
-            $outputLength = (int) $outputLength;
366
-        }
367
-
368
-        /* Input validation: */
369
-        if (!empty($key)) {
370
-            if (self::strlen($key) < ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
371
-                throw new TypeError('Argument 2 must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes');
372
-            }
373
-            if (self::strlen($key) > ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
374
-                throw new TypeError('Argument 2 must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes');
375
-            }
376
-        }
377
-        if ($outputLength < ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MIN) {
378
-            throw new Error('Argument 3 must be at least CRYPTO_GENERICHASH_BYTES_MIN');
379
-        }
380
-        if ($outputLength > ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MAX) {
381
-            throw new Error('Argument 3 must be at least CRYPTO_GENERICHASH_BYTES_MAX');
382
-        }
383
-
384
-        /** @var int $size */
385
-        $size = filesize($filePath);
386
-        if (!is_int($size)) {
387
-            throw new Error('Could not obtain the file size');
388
-        }
389
-
390
-        /** @var resource $fp */
391
-        $fp = fopen($filePath, 'rb');
392
-        if (!is_resource($fp)) {
393
-            throw new Error('Could not open input file for reading');
394
-        }
395
-        $ctx = ParagonIE_Sodium_Compat::crypto_generichash_init($key, $outputLength);
396
-        while ($size > 0) {
397
-            $blockSize = $size > 64
398
-                ? 64
399
-                : $size;
400
-            $read = fread($fp, $blockSize);
401
-            if (!is_string($read)) {
402
-                throw new Error('Could not read input file');
403
-            }
404
-            ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $read);
405
-            $size -= $blockSize;
406
-        }
407
-
408
-        fclose($fp);
409
-        return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx, $outputLength);
410
-    }
411
-
412
-    /**
413
-     * Encrypt a file (rather than a string). Uses less memory than
414
-     * ParagonIE_Sodium_Compat::crypto_secretbox(), but produces
415
-     * the same result.
416
-     *
417
-     * @param string $inputFile  Absolute path to a file on the filesystem
418
-     * @param string $outputFile Absolute path to a file on the filesystem
419
-     * @param string $nonce      Number to be used only once
420
-     * @param string $key        Encryption key
421
-     *
422
-     * @return bool
423
-     * @throws Error
424
-     * @throws TypeError
425
-     */
426
-    public static function secretbox($inputFile, $outputFile, $nonce, $key)
427
-    {
428
-        /* Type checks: */
429
-        if (!is_string($inputFile)) {
430
-            throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given..');
431
-        }
432
-        if (!is_string($outputFile)) {
433
-            throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
434
-        }
435
-        if (!is_string($nonce)) {
436
-            throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
437
-        }
438
-
439
-        /* Input validation: */
440
-        if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) {
441
-            throw new TypeError('Argument 3 must be CRYPTO_SECRETBOX_NONCEBYTES bytes');
442
-        }
443
-        if (!is_string($key)) {
444
-            throw new TypeError('Argument 4 must be a string, ' . gettype($key) . ' given.');
445
-        }
446
-        if (self::strlen($key) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) {
447
-            throw new TypeError('Argument 4 must be CRYPTO_SECRETBOX_KEYBYTES bytes');
448
-        }
449
-
450
-        /** @var int $size */
451
-        $size = filesize($inputFile);
452
-        if (!is_int($size)) {
453
-            throw new Error('Could not obtain the file size');
454
-        }
455
-
456
-        /** @var resource $ifp */
457
-        $ifp = fopen($inputFile, 'rb');
458
-        if (!is_resource($ifp)) {
459
-            throw new Error('Could not open input file for reading');
460
-        }
461
-
462
-        /** @var resource $ofp */
463
-        $ofp = fopen($outputFile, 'wb');
464
-        if (!is_resource($ofp)) {
465
-            fclose($ifp);
466
-            throw new Error('Could not open output file for writing');
467
-        }
468
-
469
-        $res = self::secretbox_encrypt($ifp, $ofp, $size, $nonce, $key);
470
-        fclose($ifp);
471
-        fclose($ofp);
472
-        return $res;
473
-    }
474
-    /**
475
-     * Seal a file (rather than a string). Uses less memory than
476
-     * ParagonIE_Sodium_Compat::crypto_secretbox_open(), but produces
477
-     * the same result.
478
-     *
479
-     * Warning: Does not protect against TOCTOU attacks. You should
480
-     * just load the file into memory and use crypto_secretbox_open() if
481
-     * you are worried about those.
482
-     *
483
-     * @param string $inputFile
484
-     * @param string $outputFile
485
-     * @param string $nonce
486
-     * @param string $key
487
-     * @return bool
488
-     * @throws Error
489
-     * @throws TypeError
490
-     */
491
-    public static function secretbox_open($inputFile, $outputFile, $nonce, $key)
492
-    {
493
-        /* Type checks: */
494
-        if (!is_string($inputFile)) {
495
-            throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
496
-        }
497
-        if (!is_string($outputFile)) {
498
-            throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
499
-        }
500
-        if (!is_string($nonce)) {
501
-            throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
502
-        }
503
-        if (!is_string($key)) {
504
-            throw new TypeError('Argument 4 must be a string, ' . gettype($key) . ' given.');
505
-        }
506
-
507
-        /* Input validation: */
508
-        if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) {
509
-            throw new TypeError('Argument 4 must be CRYPTO_SECRETBOX_NONCEBYTES bytes');
510
-        }
511
-        if (self::strlen($key) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) {
512
-            throw new TypeError('Argument 4 must be CRYPTO_SECRETBOXBOX_KEYBYTES bytes');
513
-        }
514
-
515
-        /** @var int $size */
516
-        $size = filesize($inputFile);
517
-        if (!is_int($size)) {
518
-            throw new Error('Could not obtain the file size');
519
-        }
520
-
521
-        /** @var resource $ifp */
522
-        $ifp = fopen($inputFile, 'rb');
523
-        if (!is_resource($ifp)) {
524
-            throw new Error('Could not open input file for reading');
525
-        }
526
-
527
-        /** @var resource $ofp */
528
-        $ofp = fopen($outputFile, 'wb');
529
-        if (!is_resource($ofp)) {
530
-            fclose($ifp);
531
-            throw new Error('Could not open output file for writing');
532
-        }
533
-
534
-        $res = self::secretbox_decrypt($ifp, $ofp, $size, $nonce, $key);
535
-        fclose($ifp);
536
-        fclose($ofp);
537
-        try {
538
-            ParagonIE_Sodium_Compat::memzero($key);
539
-        } catch (Error $ex) {
540
-            unset($key);
541
-        }
542
-        return $res;
543
-    }
544
-
545
-    /**
546
-     * Sign a file (rather than a string). Uses less memory than
547
-     * ParagonIE_Sodium_Compat::crypto_sign_detached(), but produces
548
-     * the same result.
549
-     *
550
-     * @param string $filePath  Absolute path to a file on the filesystem
551
-     * @param string $secretKey Secret signing key
552
-     *
553
-     * @return string           Ed25519 signature
554
-     * @throws Error
555
-     * @throws TypeError
556
-     */
557
-    public static function sign($filePath, $secretKey)
558
-    {
559
-        /* Type checks: */
560
-        if (!is_string($filePath)) {
561
-            throw new TypeError('Argument 1 must be a string, ' . gettype($filePath) . ' given.');
562
-        }
563
-        if (!is_string($secretKey)) {
564
-            throw new TypeError('Argument 2 must be a string, ' . gettype($secretKey) . ' given.');
565
-        }
566
-
567
-        /* Input validation: */
568
-        if (self::strlen($secretKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_SECRETKEYBYTES) {
569
-            throw new TypeError('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES bytes');
570
-        }
571
-
572
-        /** @var int $size */
573
-        $size = filesize($filePath);
574
-        if (!is_int($size)) {
575
-            throw new Error('Could not obtain the file size');
576
-        }
577
-
578
-        /** @var resource $fp */
579
-        $fp = fopen($filePath, 'rb');
580
-        if (!is_resource($fp)) {
581
-            throw new Error('Could not open input file for reading');
582
-        }
583
-
584
-        /** @var string $az */
585
-        $az = hash('sha512', self::substr($secretKey, 0, 32), true);
586
-
587
-        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
588
-        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
589
-
590
-        /** @var resource $hs */
591
-        $hs = hash_init('sha512');
592
-        hash_update($hs, self::substr($az, 32, 32));
593
-        $hs = self::updateHashWithFile($hs, $fp, $size);
594
-
595
-        /** @var string $nonceHash */
596
-        $nonceHash = hash_final($hs, true);
597
-
598
-        /** @var string $pk */
599
-        $pk = self::substr($secretKey, 32, 32);
600
-
601
-        /** @var string $nonce */
602
-        $nonce = ParagonIE_Sodium_Core_Ed25519::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
603
-
604
-        /** @var string $sig */
605
-        $sig = ParagonIE_Sodium_Core_Ed25519::ge_p3_tobytes(
606
-            ParagonIE_Sodium_Core_Ed25519::ge_scalarmult_base($nonce)
607
-        );
608
-
609
-        /** @var resource $hs */
610
-        $hs = hash_init('sha512');
611
-        hash_update($hs, self::substr($sig, 0, 32));
612
-        hash_update($hs, self::substr($pk, 0, 32));
613
-        $hs = self::updateHashWithFile($hs, $fp, $size);
614
-
615
-        /** @var string $hramHash */
616
-        $hramHash = hash_final($hs, true);
617
-
618
-        /** @var string $hram */
619
-        $hram = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hramHash);
620
-
621
-        /** @var string $sigAfter */
622
-        $sigAfter = ParagonIE_Sodium_Core_Ed25519::sc_muladd($hram, $az, $nonce);
623
-
624
-        /** @var string $sig */
625
-        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
626
-
627
-        try {
628
-            ParagonIE_Sodium_Compat::memzero($az);
629
-        } catch (Error $ex) {
630
-            $az = null;
631
-        }
632
-        fclose($fp);
633
-        return $sig;
634
-    }
635
-
636
-    /**
637
-     * Verify a file (rather than a string). Uses less memory than
638
-     * ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but
639
-     * produces the same result.
640
-     *
641
-     * @param string $sig       Ed25519 signature
642
-     * @param string $filePath  Absolute path to a file on the filesystem
643
-     * @param string $publicKey Signing public key
644
-     *
645
-     * @return bool
646
-     * @throws Error
647
-     * @throws Exception
648
-     */
649
-    public static function verify($sig, $filePath, $publicKey)
650
-    {
651
-        /* Type checks: */
652
-        if (!is_string($sig)) {
653
-            throw new TypeError('Argument 1 must be a string, ' . gettype($sig) . ' given.');
654
-        }
655
-        if (!is_string($filePath)) {
656
-            throw new TypeError('Argument 2 must be a string, ' . gettype($filePath) . ' given.');
657
-        }
658
-        if (!is_string($publicKey)) {
659
-            throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.');
660
-        }
661
-
662
-        /* Input validation: */
663
-        if (self::strlen($sig) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES) {
664
-            throw new TypeError('Argument 1 must be CRYPTO_SIGN_BYTES bytes');
665
-        }
666
-        if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES) {
667
-            throw new TypeError('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES bytes');
668
-        }
669
-        if (self::strlen($sig) < 64) {
670
-            throw new Exception('Signature is too short');
671
-        }
672
-
673
-        /* Security checks */
674
-        if (ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig, 32, 32))) {
675
-            throw new Exception('S < L - Invalid signature');
676
-        }
677
-        if (ParagonIE_Sodium_Core_Ed25519::small_order($sig)) {
678
-            throw new Exception('Signature is on too small of an order');
679
-        }
680
-        if ((self::chrToInt($sig[63]) & 224) !== 0) {
681
-            throw new Exception('Invalid signature');
682
-        }
683
-        $d = 0;
684
-        for ($i = 0; $i < 32; ++$i) {
685
-            $d |= self::chrToInt($publicKey[$i]);
686
-        }
687
-        if ($d === 0) {
688
-            throw new Exception('All zero public key');
689
-        }
690
-
691
-        /** @var int $size */
692
-        $size = filesize($filePath);
693
-        if (!is_int($size)) {
694
-            throw new Error('Could not obtain the file size');
695
-        }
696
-
697
-        /** @var resource $fp */
698
-        $fp = fopen($filePath, 'rb');
699
-        if (!is_resource($fp)) {
700
-            throw new Error('Could not open input file for reading');
701
-        }
702
-
703
-        /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
704
-        $orig = ParagonIE_Sodium_Compat::$fastMult;
705
-
706
-        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
707
-        ParagonIE_Sodium_Compat::$fastMult = true;
708
-
709
-        /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */
710
-        $A = ParagonIE_Sodium_Core_Ed25519::ge_frombytes_negate_vartime($publicKey);
711
-
712
-        /** @var resource $hs */
713
-        $hs = hash_init('sha512');
714
-        hash_update($hs, self::substr($sig, 0, 32));
715
-        hash_update($hs, self::substr($publicKey, 0, 32));
716
-        $hs = self::updateHashWithFile($hs, $fp, $size);
717
-        /** @var string $hDigest */
718
-        $hDigest = hash_final($hs, true);
719
-
720
-        /** @var string $h */
721
-        $h = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hDigest) . self::substr($hDigest, 32);
722
-
723
-        /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */
724
-        $R = ParagonIE_Sodium_Core_Ed25519::ge_double_scalarmult_vartime(
725
-            $h,
726
-            $A,
727
-            self::substr($sig, 32)
728
-        );
729
-
730
-        /** @var string $rcheck */
731
-        $rcheck = ParagonIE_Sodium_Core_Ed25519::ge_tobytes($R);
732
-
733
-        // Close the file handle
734
-        fclose($fp);
735
-
736
-        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
737
-        ParagonIE_Sodium_Compat::$fastMult = $orig;
738
-        return self::verify_32($rcheck, self::substr($sig, 0, 32));
739
-    }
740
-
741
-    /**
742
-     * @param resource $ifp
743
-     * @param resource $ofp
744
-     * @param int      $mlen
745
-     * @param string   $nonce
746
-     * @param string   $boxKeypair
747
-     * @return bool
748
-     */
749
-    protected static function box_encrypt($ifp, $ofp, $mlen, $nonce, $boxKeypair)
750
-    {
751
-        return self::secretbox_encrypt(
752
-            $ifp,
753
-            $ofp,
754
-            $mlen,
755
-            $nonce,
756
-            ParagonIE_Sodium_Crypto::box_beforenm(
757
-                ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair),
758
-                ParagonIE_Sodium_Crypto::box_publickey($boxKeypair)
759
-            )
760
-        );
761
-    }
762
-
763
-
764
-    /**
765
-     * @param resource $ifp
766
-     * @param resource $ofp
767
-     * @param int      $mlen
768
-     * @param string   $nonce
769
-     * @param string   $boxKeypair
770
-     * @return bool
771
-     */
772
-    protected static function box_decrypt($ifp, $ofp, $mlen, $nonce, $boxKeypair)
773
-    {
774
-        return self::secretbox_decrypt(
775
-            $ifp,
776
-            $ofp,
777
-            $mlen,
778
-            $nonce,
779
-            ParagonIE_Sodium_Crypto::box_beforenm(
780
-                ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair),
781
-                ParagonIE_Sodium_Crypto::box_publickey($boxKeypair)
782
-            )
783
-        );
784
-    }
785
-
786
-    /**
787
-     * Encrypt a file
788
-     *
789
-     * @param resource $ifp
790
-     * @param resource $ofp
791
-     * @param int $mlen
792
-     * @param string $nonce
793
-     * @param string $key
794
-     * @return bool
795
-     * @throws Error
796
-     */
797
-    protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce, $key)
798
-    {
799
-        $plaintext = fread($ifp, 32);
800
-        if (!is_string($plaintext)) {
801
-            throw new Error('Could not read input file');
802
-        }
803
-        $first32 = ftell($ifp);
804
-
805
-        /** @var string $subkey */
806
-        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
807
-
808
-        /** @var string $realNonce */
809
-        $realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
810
-
811
-        /** @var string $block0 */
812
-        $block0 = str_repeat("\x00", 32);
813
-
814
-        /** @var int $mlen - Length of the plaintext message */
815
-        $mlen0 = $mlen;
816
-        if ($mlen0 > 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES) {
817
-            $mlen0 = 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES;
818
-        }
819
-        $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0);
820
-
821
-        /** @var string $block0 */
822
-        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
823
-            $block0,
824
-            $realNonce,
825
-            $subkey
826
-        );
827
-
828
-        $state = new ParagonIE_Sodium_Core_Poly1305_State(
829
-            ParagonIE_Sodium_Core_Util::substr(
830
-                $block0,
831
-                0,
832
-                ParagonIE_Sodium_Crypto::onetimeauth_poly1305_KEYBYTES
833
-            )
834
-        );
835
-
836
-        // Pre-write 16 blank bytes for the Poly1305 tag
837
-        $start = ftell($ofp);
838
-        fwrite($ofp, str_repeat("\x00", 16));
839
-
840
-        /** @var string $c */
841
-        $cBlock = ParagonIE_Sodium_Core_Util::substr(
842
-            $block0,
843
-            ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES
844
-        );
845
-        $state->update($cBlock);
846
-        fwrite($ofp, $cBlock);
847
-        $mlen -= 32;
848
-
849
-        /** @var int $iter */
850
-        $iter = 1;
851
-
852
-        /** @var int $incr */
853
-        $incr = self::BUFFER_SIZE >> 6;
854
-
855
-        /*
11
+	/* PHP's default buffer size is 8192 for fread()/fwrite(). */
12
+	const BUFFER_SIZE = 8192;
13
+
14
+	/**
15
+	 * Box a file (rather than a string). Uses less memory than
16
+	 * ParagonIE_Sodium_Compat::crypto_box(), but produces
17
+	 * the same result.
18
+	 *
19
+	 * @param string $inputFile  Absolute path to a file on the filesystem
20
+	 * @param string $outputFile Absolute path to a file on the filesystem
21
+	 * @param string $nonce      Number to be used only once
22
+	 * @param string $keyPair    ECDH secret key and ECDH public key concatenated
23
+	 *
24
+	 * @return bool
25
+	 * @throws Error
26
+	 * @throws TypeError
27
+	 */
28
+	public static function box($inputFile, $outputFile, $nonce, $keyPair)
29
+	{
30
+		/* Type checks: */
31
+		if (!is_string($inputFile)) {
32
+			throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
33
+		}
34
+		if (!is_string($outputFile)) {
35
+			throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
36
+		}
37
+		if (!is_string($nonce)) {
38
+			throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
39
+		}
40
+
41
+		/* Input validation: */
42
+		if (!is_string($keyPair)) {
43
+			throw new TypeError('Argument 4 must be a string, ' . gettype($keyPair) . ' given.');
44
+		}
45
+		if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
46
+			throw new TypeError('Argument 3 must be CRYPTO_BOX_NONCEBYTES bytes');
47
+		}
48
+		if (self::strlen($keyPair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
49
+			throw new TypeError('Argument 4 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
50
+		}
51
+
52
+		/** @var int $size */
53
+		$size = filesize($inputFile);
54
+		if (!is_int($size)) {
55
+			throw new Error('Could not obtain the file size');
56
+		}
57
+
58
+		/** @var resource $ifp */
59
+		$ifp = fopen($inputFile, 'rb');
60
+		if (!is_resource($ifp)) {
61
+			throw new Error('Could not open input file for reading');
62
+		}
63
+
64
+		/** @var resource $ofp */
65
+		$ofp = fopen($outputFile, 'wb');
66
+		if (!is_resource($ofp)) {
67
+			fclose($ifp);
68
+			throw new Error('Could not open output file for writing');
69
+		}
70
+
71
+		$res = self::box_encrypt($ifp, $ofp, $size, $nonce, $keyPair);
72
+		fclose($ifp);
73
+		fclose($ofp);
74
+		return $res;
75
+	}
76
+
77
+	/**
78
+	 * Open a boxed file (rather than a string). Uses less memory than
79
+	 * ParagonIE_Sodium_Compat::crypto_box_open(), but produces
80
+	 * the same result.
81
+	 *
82
+	 * Warning: Does not protect against TOCTOU attacks. You should
83
+	 * just load the file into memory and use crypto_box_open() if
84
+	 * you are worried about those.
85
+	 *
86
+	 * @param string $inputFile
87
+	 * @param string $outputFile
88
+	 * @param string $nonce
89
+	 * @param string $keypair
90
+	 * @return bool
91
+	 * @throws Error
92
+	 * @throws TypeError
93
+	 */
94
+	public static function box_open($inputFile, $outputFile, $nonce, $keypair)
95
+	{
96
+		/* Type checks: */
97
+		if (!is_string($inputFile)) {
98
+			throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
99
+		}
100
+		if (!is_string($outputFile)) {
101
+			throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
102
+		}
103
+		if (!is_string($nonce)) {
104
+			throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
105
+		}
106
+		if (!is_string($keypair)) {
107
+			throw new TypeError('Argument 4 must be a string, ' . gettype($keypair) . ' given.');
108
+		}
109
+
110
+		/* Input validation: */
111
+		if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
112
+			throw new TypeError('Argument 4 must be CRYPTO_BOX_NONCEBYTES bytes');
113
+		}
114
+		if (self::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
115
+			throw new TypeError('Argument 4 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
116
+		}
117
+
118
+		/** @var int $size */
119
+		$size = filesize($inputFile);
120
+		if (!is_int($size)) {
121
+			throw new Error('Could not obtain the file size');
122
+		}
123
+
124
+		/** @var resource $ifp */
125
+		$ifp = fopen($inputFile, 'rb');
126
+		if (!is_resource($ifp)) {
127
+			throw new Error('Could not open input file for reading');
128
+		}
129
+
130
+		/** @var resource $ofp */
131
+		$ofp = fopen($outputFile, 'wb');
132
+		if (!is_resource($ofp)) {
133
+			fclose($ifp);
134
+			throw new Error('Could not open output file for writing');
135
+		}
136
+
137
+		$res = self::box_decrypt($ifp, $ofp, $size, $nonce, $keypair);
138
+		fclose($ifp);
139
+		fclose($ofp);
140
+		try {
141
+			ParagonIE_Sodium_Compat::memzero($nonce);
142
+			ParagonIE_Sodium_Compat::memzero($ephKeypair);
143
+		} catch (Error $ex) {
144
+			unset($ephKeypair);
145
+		}
146
+		return $res;
147
+	}
148
+
149
+	/**
150
+	 * Seal a file (rather than a string). Uses less memory than
151
+	 * ParagonIE_Sodium_Compat::crypto_box_seal(), but produces
152
+	 * the same result.
153
+	 *
154
+	 * @param string $inputFile  Absolute path to a file on the filesystem
155
+	 * @param string $outputFile Absolute path to a file on the filesystem
156
+	 * @param string $publicKey  ECDH public key
157
+	 *
158
+	 * @return bool
159
+	 * @throws Error
160
+	 * @throws TypeError
161
+	 */
162
+	public static function box_seal($inputFile, $outputFile, $publicKey)
163
+	{
164
+		/* Type checks: */
165
+		if (!is_string($inputFile)) {
166
+			throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
167
+		}
168
+		if (!is_string($outputFile)) {
169
+			throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
170
+		}
171
+		if (!is_string($publicKey)) {
172
+			throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.');
173
+		}
174
+
175
+		/* Input validation: */
176
+		if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
177
+			throw new TypeError('Argument 3 must be CRYPTO_BOX_PUBLICKEYBYTES bytes');
178
+		}
179
+
180
+		/** @var int $size */
181
+		$size = filesize($inputFile);
182
+		if (!is_int($size)) {
183
+			throw new Error('Could not obtain the file size');
184
+		}
185
+
186
+		/** @var resource $ifp */
187
+		$ifp = fopen($inputFile, 'rb');
188
+		if (!is_resource($ifp)) {
189
+			throw new Error('Could not open input file for reading');
190
+		}
191
+
192
+		/** @var resource $ofp */
193
+		$ofp = fopen($outputFile, 'wb');
194
+		if (!is_resource($ofp)) {
195
+			fclose($ifp);
196
+			throw new Error('Could not open output file for writing');
197
+		}
198
+
199
+		/** @var string $ephKeypair */
200
+		$ephKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair();
201
+
202
+		/** @var string $msgKeypair */
203
+		$msgKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
204
+			ParagonIE_Sodium_Compat::crypto_box_secretkey($ephKeypair),
205
+			$publicKey
206
+		);
207
+
208
+		/** @var string $ephemeralPK */
209
+		$ephemeralPK = ParagonIE_Sodium_Compat::crypto_box_publickey($ephKeypair);
210
+
211
+		/** @var string $nonce */
212
+		$nonce = ParagonIE_Sodium_Compat::crypto_generichash(
213
+			$ephemeralPK . $publicKey,
214
+			'',
215
+			24
216
+		);
217
+
218
+		/** @var int $firstWrite */
219
+		$firstWrite = fwrite(
220
+			$ofp,
221
+			$ephemeralPK,
222
+			ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES
223
+		);
224
+		if (!is_int($firstWrite)) {
225
+			fclose($ifp);
226
+			fclose($ofp);
227
+			ParagonIE_Sodium_Compat::memzero($ephKeypair);
228
+			throw new Error('Could not write to output file');
229
+		}
230
+		if ($firstWrite !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
231
+			ParagonIE_Sodium_Compat::memzero($ephKeypair);
232
+			fclose($ifp);
233
+			fclose($ofp);
234
+			throw new Error('Error writing public key to output file');
235
+		}
236
+
237
+		$res = self::box_encrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
238
+		fclose($ifp);
239
+		fclose($ofp);
240
+		try {
241
+			ParagonIE_Sodium_Compat::memzero($nonce);
242
+			ParagonIE_Sodium_Compat::memzero($ephKeypair);
243
+		} catch (Error $ex) {
244
+			unset($ephKeypair);
245
+		}
246
+		return $res;
247
+	}
248
+
249
+	/**
250
+	 * Open a sealed file (rather than a string). Uses less memory than
251
+	 * ParagonIE_Sodium_Compat::crypto_box_seal_open(), but produces
252
+	 * the same result.
253
+	 *
254
+	 * Warning: Does not protect against TOCTOU attacks. You should
255
+	 * just load the file into memory and use crypto_box_seal_open() if
256
+	 * you are worried about those.
257
+	 *
258
+	 * @param string $inputFile
259
+	 * @param string $outputFile
260
+	 * @param string $ecdhKeypair
261
+	 * @return bool
262
+	 * @throws Error
263
+	 * @throws TypeError
264
+	 */
265
+	public static function box_seal_open($inputFile, $outputFile, $ecdhKeypair)
266
+	{
267
+		/* Type checks: */
268
+		if (!is_string($inputFile)) {
269
+			throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
270
+		}
271
+		if (!is_string($outputFile)) {
272
+			throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
273
+		}
274
+		if (!is_string($ecdhKeypair)) {
275
+			throw new TypeError('Argument 3 must be a string, ' . gettype($ecdhKeypair) . ' given.');
276
+		}
277
+
278
+		/* Input validation: */
279
+		if (self::strlen($ecdhKeypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
280
+			throw new TypeError('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
281
+		}
282
+
283
+		$publicKey = ParagonIE_Sodium_Compat::crypto_box_publickey($ecdhKeypair);
284
+
285
+		/** @var int $size */
286
+		$size = filesize($inputFile);
287
+		if (!is_int($size)) {
288
+			throw new Error('Could not obtain the file size');
289
+		}
290
+
291
+		/** @var resource $ifp */
292
+		$ifp = fopen($inputFile, 'rb');
293
+		if (!is_resource($ifp)) {
294
+			throw new Error('Could not open input file for reading');
295
+		}
296
+
297
+		/** @var resource $ofp */
298
+		$ofp = fopen($outputFile, 'wb');
299
+		if (!is_resource($ofp)) {
300
+			fclose($ifp);
301
+			throw new Error('Could not open output file for writing');
302
+		}
303
+
304
+		$ephemeralPK = fread($ifp, ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES);
305
+		if (!is_string($ephemeralPK)) {
306
+			throw new Error('Could not read input file');
307
+		}
308
+		if (self::strlen($ephemeralPK) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
309
+			fclose($ifp);
310
+			fclose($ofp);
311
+			throw new Error('Could not read public key from sealed file');
312
+		}
313
+
314
+		$nonce = ParagonIE_Sodium_Compat::crypto_generichash(
315
+			$ephemeralPK . $publicKey,
316
+			'',
317
+			24
318
+		);
319
+		$msgKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
320
+			ParagonIE_Sodium_Compat::crypto_box_secretkey($ecdhKeypair),
321
+			$ephemeralPK
322
+		);
323
+
324
+		$res = self::box_decrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
325
+		fclose($ifp);
326
+		fclose($ofp);
327
+		try {
328
+			ParagonIE_Sodium_Compat::memzero($nonce);
329
+			ParagonIE_Sodium_Compat::memzero($ephKeypair);
330
+		} catch (Error $ex) {
331
+			unset($ephKeypair);
332
+		}
333
+		return $res;
334
+	}
335
+
336
+	/**
337
+	 * Calculate the BLAKE2b hash of a file.
338
+	 *
339
+	 * @param string      $filePath     Absolute path to a file on the filesystem
340
+	 * @param string|null $key          BLAKE2b key
341
+	 * @param int         $outputLength Length of hash output
342
+	 *
343
+	 * @return string                   BLAKE2b hash
344
+	 * @throws Error
345
+	 * @throws TypeError
346
+	 * @psalm-suppress FailedTypeResolution
347
+	 */
348
+	public static function generichash($filePath, $key = '', $outputLength = 32)
349
+	{
350
+		/* Type checks: */
351
+		if (!is_string($filePath)) {
352
+			throw new TypeError('Argument 1 must be a string, ' . gettype($filePath) . ' given.');
353
+		}
354
+		if (!is_string($key)) {
355
+			if (is_null($key)) {
356
+				$key = '';
357
+			} else {
358
+				throw new TypeError('Argument 2 must be a string, ' . gettype($key) . ' given.');
359
+			}
360
+		}
361
+		if (!is_int($outputLength)) {
362
+			if (!is_numeric($outputLength)) {
363
+				throw new TypeError('Argument 3 must be an integer, ' . gettype($outputLength) . ' given.');
364
+			}
365
+			$outputLength = (int) $outputLength;
366
+		}
367
+
368
+		/* Input validation: */
369
+		if (!empty($key)) {
370
+			if (self::strlen($key) < ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
371
+				throw new TypeError('Argument 2 must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes');
372
+			}
373
+			if (self::strlen($key) > ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
374
+				throw new TypeError('Argument 2 must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes');
375
+			}
376
+		}
377
+		if ($outputLength < ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MIN) {
378
+			throw new Error('Argument 3 must be at least CRYPTO_GENERICHASH_BYTES_MIN');
379
+		}
380
+		if ($outputLength > ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MAX) {
381
+			throw new Error('Argument 3 must be at least CRYPTO_GENERICHASH_BYTES_MAX');
382
+		}
383
+
384
+		/** @var int $size */
385
+		$size = filesize($filePath);
386
+		if (!is_int($size)) {
387
+			throw new Error('Could not obtain the file size');
388
+		}
389
+
390
+		/** @var resource $fp */
391
+		$fp = fopen($filePath, 'rb');
392
+		if (!is_resource($fp)) {
393
+			throw new Error('Could not open input file for reading');
394
+		}
395
+		$ctx = ParagonIE_Sodium_Compat::crypto_generichash_init($key, $outputLength);
396
+		while ($size > 0) {
397
+			$blockSize = $size > 64
398
+				? 64
399
+				: $size;
400
+			$read = fread($fp, $blockSize);
401
+			if (!is_string($read)) {
402
+				throw new Error('Could not read input file');
403
+			}
404
+			ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $read);
405
+			$size -= $blockSize;
406
+		}
407
+
408
+		fclose($fp);
409
+		return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx, $outputLength);
410
+	}
411
+
412
+	/**
413
+	 * Encrypt a file (rather than a string). Uses less memory than
414
+	 * ParagonIE_Sodium_Compat::crypto_secretbox(), but produces
415
+	 * the same result.
416
+	 *
417
+	 * @param string $inputFile  Absolute path to a file on the filesystem
418
+	 * @param string $outputFile Absolute path to a file on the filesystem
419
+	 * @param string $nonce      Number to be used only once
420
+	 * @param string $key        Encryption key
421
+	 *
422
+	 * @return bool
423
+	 * @throws Error
424
+	 * @throws TypeError
425
+	 */
426
+	public static function secretbox($inputFile, $outputFile, $nonce, $key)
427
+	{
428
+		/* Type checks: */
429
+		if (!is_string($inputFile)) {
430
+			throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given..');
431
+		}
432
+		if (!is_string($outputFile)) {
433
+			throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
434
+		}
435
+		if (!is_string($nonce)) {
436
+			throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
437
+		}
438
+
439
+		/* Input validation: */
440
+		if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) {
441
+			throw new TypeError('Argument 3 must be CRYPTO_SECRETBOX_NONCEBYTES bytes');
442
+		}
443
+		if (!is_string($key)) {
444
+			throw new TypeError('Argument 4 must be a string, ' . gettype($key) . ' given.');
445
+		}
446
+		if (self::strlen($key) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) {
447
+			throw new TypeError('Argument 4 must be CRYPTO_SECRETBOX_KEYBYTES bytes');
448
+		}
449
+
450
+		/** @var int $size */
451
+		$size = filesize($inputFile);
452
+		if (!is_int($size)) {
453
+			throw new Error('Could not obtain the file size');
454
+		}
455
+
456
+		/** @var resource $ifp */
457
+		$ifp = fopen($inputFile, 'rb');
458
+		if (!is_resource($ifp)) {
459
+			throw new Error('Could not open input file for reading');
460
+		}
461
+
462
+		/** @var resource $ofp */
463
+		$ofp = fopen($outputFile, 'wb');
464
+		if (!is_resource($ofp)) {
465
+			fclose($ifp);
466
+			throw new Error('Could not open output file for writing');
467
+		}
468
+
469
+		$res = self::secretbox_encrypt($ifp, $ofp, $size, $nonce, $key);
470
+		fclose($ifp);
471
+		fclose($ofp);
472
+		return $res;
473
+	}
474
+	/**
475
+	 * Seal a file (rather than a string). Uses less memory than
476
+	 * ParagonIE_Sodium_Compat::crypto_secretbox_open(), but produces
477
+	 * the same result.
478
+	 *
479
+	 * Warning: Does not protect against TOCTOU attacks. You should
480
+	 * just load the file into memory and use crypto_secretbox_open() if
481
+	 * you are worried about those.
482
+	 *
483
+	 * @param string $inputFile
484
+	 * @param string $outputFile
485
+	 * @param string $nonce
486
+	 * @param string $key
487
+	 * @return bool
488
+	 * @throws Error
489
+	 * @throws TypeError
490
+	 */
491
+	public static function secretbox_open($inputFile, $outputFile, $nonce, $key)
492
+	{
493
+		/* Type checks: */
494
+		if (!is_string($inputFile)) {
495
+			throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.');
496
+		}
497
+		if (!is_string($outputFile)) {
498
+			throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.');
499
+		}
500
+		if (!is_string($nonce)) {
501
+			throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.');
502
+		}
503
+		if (!is_string($key)) {
504
+			throw new TypeError('Argument 4 must be a string, ' . gettype($key) . ' given.');
505
+		}
506
+
507
+		/* Input validation: */
508
+		if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) {
509
+			throw new TypeError('Argument 4 must be CRYPTO_SECRETBOX_NONCEBYTES bytes');
510
+		}
511
+		if (self::strlen($key) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) {
512
+			throw new TypeError('Argument 4 must be CRYPTO_SECRETBOXBOX_KEYBYTES bytes');
513
+		}
514
+
515
+		/** @var int $size */
516
+		$size = filesize($inputFile);
517
+		if (!is_int($size)) {
518
+			throw new Error('Could not obtain the file size');
519
+		}
520
+
521
+		/** @var resource $ifp */
522
+		$ifp = fopen($inputFile, 'rb');
523
+		if (!is_resource($ifp)) {
524
+			throw new Error('Could not open input file for reading');
525
+		}
526
+
527
+		/** @var resource $ofp */
528
+		$ofp = fopen($outputFile, 'wb');
529
+		if (!is_resource($ofp)) {
530
+			fclose($ifp);
531
+			throw new Error('Could not open output file for writing');
532
+		}
533
+
534
+		$res = self::secretbox_decrypt($ifp, $ofp, $size, $nonce, $key);
535
+		fclose($ifp);
536
+		fclose($ofp);
537
+		try {
538
+			ParagonIE_Sodium_Compat::memzero($key);
539
+		} catch (Error $ex) {
540
+			unset($key);
541
+		}
542
+		return $res;
543
+	}
544
+
545
+	/**
546
+	 * Sign a file (rather than a string). Uses less memory than
547
+	 * ParagonIE_Sodium_Compat::crypto_sign_detached(), but produces
548
+	 * the same result.
549
+	 *
550
+	 * @param string $filePath  Absolute path to a file on the filesystem
551
+	 * @param string $secretKey Secret signing key
552
+	 *
553
+	 * @return string           Ed25519 signature
554
+	 * @throws Error
555
+	 * @throws TypeError
556
+	 */
557
+	public static function sign($filePath, $secretKey)
558
+	{
559
+		/* Type checks: */
560
+		if (!is_string($filePath)) {
561
+			throw new TypeError('Argument 1 must be a string, ' . gettype($filePath) . ' given.');
562
+		}
563
+		if (!is_string($secretKey)) {
564
+			throw new TypeError('Argument 2 must be a string, ' . gettype($secretKey) . ' given.');
565
+		}
566
+
567
+		/* Input validation: */
568
+		if (self::strlen($secretKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_SECRETKEYBYTES) {
569
+			throw new TypeError('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES bytes');
570
+		}
571
+
572
+		/** @var int $size */
573
+		$size = filesize($filePath);
574
+		if (!is_int($size)) {
575
+			throw new Error('Could not obtain the file size');
576
+		}
577
+
578
+		/** @var resource $fp */
579
+		$fp = fopen($filePath, 'rb');
580
+		if (!is_resource($fp)) {
581
+			throw new Error('Could not open input file for reading');
582
+		}
583
+
584
+		/** @var string $az */
585
+		$az = hash('sha512', self::substr($secretKey, 0, 32), true);
586
+
587
+		$az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
588
+		$az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
589
+
590
+		/** @var resource $hs */
591
+		$hs = hash_init('sha512');
592
+		hash_update($hs, self::substr($az, 32, 32));
593
+		$hs = self::updateHashWithFile($hs, $fp, $size);
594
+
595
+		/** @var string $nonceHash */
596
+		$nonceHash = hash_final($hs, true);
597
+
598
+		/** @var string $pk */
599
+		$pk = self::substr($secretKey, 32, 32);
600
+
601
+		/** @var string $nonce */
602
+		$nonce = ParagonIE_Sodium_Core_Ed25519::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
603
+
604
+		/** @var string $sig */
605
+		$sig = ParagonIE_Sodium_Core_Ed25519::ge_p3_tobytes(
606
+			ParagonIE_Sodium_Core_Ed25519::ge_scalarmult_base($nonce)
607
+		);
608
+
609
+		/** @var resource $hs */
610
+		$hs = hash_init('sha512');
611
+		hash_update($hs, self::substr($sig, 0, 32));
612
+		hash_update($hs, self::substr($pk, 0, 32));
613
+		$hs = self::updateHashWithFile($hs, $fp, $size);
614
+
615
+		/** @var string $hramHash */
616
+		$hramHash = hash_final($hs, true);
617
+
618
+		/** @var string $hram */
619
+		$hram = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hramHash);
620
+
621
+		/** @var string $sigAfter */
622
+		$sigAfter = ParagonIE_Sodium_Core_Ed25519::sc_muladd($hram, $az, $nonce);
623
+
624
+		/** @var string $sig */
625
+		$sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
626
+
627
+		try {
628
+			ParagonIE_Sodium_Compat::memzero($az);
629
+		} catch (Error $ex) {
630
+			$az = null;
631
+		}
632
+		fclose($fp);
633
+		return $sig;
634
+	}
635
+
636
+	/**
637
+	 * Verify a file (rather than a string). Uses less memory than
638
+	 * ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but
639
+	 * produces the same result.
640
+	 *
641
+	 * @param string $sig       Ed25519 signature
642
+	 * @param string $filePath  Absolute path to a file on the filesystem
643
+	 * @param string $publicKey Signing public key
644
+	 *
645
+	 * @return bool
646
+	 * @throws Error
647
+	 * @throws Exception
648
+	 */
649
+	public static function verify($sig, $filePath, $publicKey)
650
+	{
651
+		/* Type checks: */
652
+		if (!is_string($sig)) {
653
+			throw new TypeError('Argument 1 must be a string, ' . gettype($sig) . ' given.');
654
+		}
655
+		if (!is_string($filePath)) {
656
+			throw new TypeError('Argument 2 must be a string, ' . gettype($filePath) . ' given.');
657
+		}
658
+		if (!is_string($publicKey)) {
659
+			throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.');
660
+		}
661
+
662
+		/* Input validation: */
663
+		if (self::strlen($sig) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES) {
664
+			throw new TypeError('Argument 1 must be CRYPTO_SIGN_BYTES bytes');
665
+		}
666
+		if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES) {
667
+			throw new TypeError('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES bytes');
668
+		}
669
+		if (self::strlen($sig) < 64) {
670
+			throw new Exception('Signature is too short');
671
+		}
672
+
673
+		/* Security checks */
674
+		if (ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig, 32, 32))) {
675
+			throw new Exception('S < L - Invalid signature');
676
+		}
677
+		if (ParagonIE_Sodium_Core_Ed25519::small_order($sig)) {
678
+			throw new Exception('Signature is on too small of an order');
679
+		}
680
+		if ((self::chrToInt($sig[63]) & 224) !== 0) {
681
+			throw new Exception('Invalid signature');
682
+		}
683
+		$d = 0;
684
+		for ($i = 0; $i < 32; ++$i) {
685
+			$d |= self::chrToInt($publicKey[$i]);
686
+		}
687
+		if ($d === 0) {
688
+			throw new Exception('All zero public key');
689
+		}
690
+
691
+		/** @var int $size */
692
+		$size = filesize($filePath);
693
+		if (!is_int($size)) {
694
+			throw new Error('Could not obtain the file size');
695
+		}
696
+
697
+		/** @var resource $fp */
698
+		$fp = fopen($filePath, 'rb');
699
+		if (!is_resource($fp)) {
700
+			throw new Error('Could not open input file for reading');
701
+		}
702
+
703
+		/** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
704
+		$orig = ParagonIE_Sodium_Compat::$fastMult;
705
+
706
+		// Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
707
+		ParagonIE_Sodium_Compat::$fastMult = true;
708
+
709
+		/** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */
710
+		$A = ParagonIE_Sodium_Core_Ed25519::ge_frombytes_negate_vartime($publicKey);
711
+
712
+		/** @var resource $hs */
713
+		$hs = hash_init('sha512');
714
+		hash_update($hs, self::substr($sig, 0, 32));
715
+		hash_update($hs, self::substr($publicKey, 0, 32));
716
+		$hs = self::updateHashWithFile($hs, $fp, $size);
717
+		/** @var string $hDigest */
718
+		$hDigest = hash_final($hs, true);
719
+
720
+		/** @var string $h */
721
+		$h = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hDigest) . self::substr($hDigest, 32);
722
+
723
+		/** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */
724
+		$R = ParagonIE_Sodium_Core_Ed25519::ge_double_scalarmult_vartime(
725
+			$h,
726
+			$A,
727
+			self::substr($sig, 32)
728
+		);
729
+
730
+		/** @var string $rcheck */
731
+		$rcheck = ParagonIE_Sodium_Core_Ed25519::ge_tobytes($R);
732
+
733
+		// Close the file handle
734
+		fclose($fp);
735
+
736
+		// Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
737
+		ParagonIE_Sodium_Compat::$fastMult = $orig;
738
+		return self::verify_32($rcheck, self::substr($sig, 0, 32));
739
+	}
740
+
741
+	/**
742
+	 * @param resource $ifp
743
+	 * @param resource $ofp
744
+	 * @param int      $mlen
745
+	 * @param string   $nonce
746
+	 * @param string   $boxKeypair
747
+	 * @return bool
748
+	 */
749
+	protected static function box_encrypt($ifp, $ofp, $mlen, $nonce, $boxKeypair)
750
+	{
751
+		return self::secretbox_encrypt(
752
+			$ifp,
753
+			$ofp,
754
+			$mlen,
755
+			$nonce,
756
+			ParagonIE_Sodium_Crypto::box_beforenm(
757
+				ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair),
758
+				ParagonIE_Sodium_Crypto::box_publickey($boxKeypair)
759
+			)
760
+		);
761
+	}
762
+
763
+
764
+	/**
765
+	 * @param resource $ifp
766
+	 * @param resource $ofp
767
+	 * @param int      $mlen
768
+	 * @param string   $nonce
769
+	 * @param string   $boxKeypair
770
+	 * @return bool
771
+	 */
772
+	protected static function box_decrypt($ifp, $ofp, $mlen, $nonce, $boxKeypair)
773
+	{
774
+		return self::secretbox_decrypt(
775
+			$ifp,
776
+			$ofp,
777
+			$mlen,
778
+			$nonce,
779
+			ParagonIE_Sodium_Crypto::box_beforenm(
780
+				ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair),
781
+				ParagonIE_Sodium_Crypto::box_publickey($boxKeypair)
782
+			)
783
+		);
784
+	}
785
+
786
+	/**
787
+	 * Encrypt a file
788
+	 *
789
+	 * @param resource $ifp
790
+	 * @param resource $ofp
791
+	 * @param int $mlen
792
+	 * @param string $nonce
793
+	 * @param string $key
794
+	 * @return bool
795
+	 * @throws Error
796
+	 */
797
+	protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce, $key)
798
+	{
799
+		$plaintext = fread($ifp, 32);
800
+		if (!is_string($plaintext)) {
801
+			throw new Error('Could not read input file');
802
+		}
803
+		$first32 = ftell($ifp);
804
+
805
+		/** @var string $subkey */
806
+		$subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
807
+
808
+		/** @var string $realNonce */
809
+		$realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
810
+
811
+		/** @var string $block0 */
812
+		$block0 = str_repeat("\x00", 32);
813
+
814
+		/** @var int $mlen - Length of the plaintext message */
815
+		$mlen0 = $mlen;
816
+		if ($mlen0 > 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES) {
817
+			$mlen0 = 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES;
818
+		}
819
+		$block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0);
820
+
821
+		/** @var string $block0 */
822
+		$block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
823
+			$block0,
824
+			$realNonce,
825
+			$subkey
826
+		);
827
+
828
+		$state = new ParagonIE_Sodium_Core_Poly1305_State(
829
+			ParagonIE_Sodium_Core_Util::substr(
830
+				$block0,
831
+				0,
832
+				ParagonIE_Sodium_Crypto::onetimeauth_poly1305_KEYBYTES
833
+			)
834
+		);
835
+
836
+		// Pre-write 16 blank bytes for the Poly1305 tag
837
+		$start = ftell($ofp);
838
+		fwrite($ofp, str_repeat("\x00", 16));
839
+
840
+		/** @var string $c */
841
+		$cBlock = ParagonIE_Sodium_Core_Util::substr(
842
+			$block0,
843
+			ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES
844
+		);
845
+		$state->update($cBlock);
846
+		fwrite($ofp, $cBlock);
847
+		$mlen -= 32;
848
+
849
+		/** @var int $iter */
850
+		$iter = 1;
851
+
852
+		/** @var int $incr */
853
+		$incr = self::BUFFER_SIZE >> 6;
854
+
855
+		/*
856 856
          * Set the cursor to the end of the first half-block. All future bytes will
857 857
          * generated from salsa20_xor_ic, starting from 1 (second block).
858 858
          */
859
-        fseek($ifp, $first32, SEEK_SET);
860
-
861
-        while ($mlen > 0) {
862
-            $blockSize = $mlen > self::BUFFER_SIZE
863
-                ? self::BUFFER_SIZE
864
-                : $mlen;
865
-            $plaintext = fread($ifp, $blockSize);
866
-            if (!is_string($plaintext)) {
867
-                throw new Error('Could not read input file');
868
-            }
869
-            $cBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
870
-                $plaintext,
871
-                $realNonce,
872
-                $iter,
873
-                $subkey
874
-            );
875
-            fwrite($ofp, $cBlock, $blockSize);
876
-            $state->update($cBlock);
877
-
878
-            $mlen -= $blockSize;
879
-            $iter += $incr;
880
-        }
881
-        try {
882
-            ParagonIE_Sodium_Compat::memzero($block0);
883
-            ParagonIE_Sodium_Compat::memzero($subkey);
884
-        } catch (Error $ex) {
885
-            $block0 = null;
886
-            $subkey = null;
887
-        }
888
-        $end = ftell($ofp);
889
-
890
-        /*
859
+		fseek($ifp, $first32, SEEK_SET);
860
+
861
+		while ($mlen > 0) {
862
+			$blockSize = $mlen > self::BUFFER_SIZE
863
+				? self::BUFFER_SIZE
864
+				: $mlen;
865
+			$plaintext = fread($ifp, $blockSize);
866
+			if (!is_string($plaintext)) {
867
+				throw new Error('Could not read input file');
868
+			}
869
+			$cBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
870
+				$plaintext,
871
+				$realNonce,
872
+				$iter,
873
+				$subkey
874
+			);
875
+			fwrite($ofp, $cBlock, $blockSize);
876
+			$state->update($cBlock);
877
+
878
+			$mlen -= $blockSize;
879
+			$iter += $incr;
880
+		}
881
+		try {
882
+			ParagonIE_Sodium_Compat::memzero($block0);
883
+			ParagonIE_Sodium_Compat::memzero($subkey);
884
+		} catch (Error $ex) {
885
+			$block0 = null;
886
+			$subkey = null;
887
+		}
888
+		$end = ftell($ofp);
889
+
890
+		/*
891 891
          * Write the Poly1305 authentication tag that provides integrity
892 892
          * over the ciphertext (encrypt-then-MAC)
893 893
          */
894
-        fseek($ofp, $start, SEEK_SET);
895
-        fwrite($ofp, $state->finish(), ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES);
896
-        fseek($ofp, $end, SEEK_SET);
897
-        unset($state);
898
-
899
-        return true;
900
-    }
901
-
902
-    /**
903
-     * Decrypt a file
904
-     *
905
-     * @param resource $ifp
906
-     * @param resource $ofp
907
-     * @param int $mlen
908
-     * @param string $nonce
909
-     * @param string $key
910
-     * @return bool
911
-     * @throws Error
912
-     * @throws Exception
913
-     */
914
-    protected static function secretbox_decrypt($ifp, $ofp, $mlen, $nonce, $key)
915
-    {
916
-        $tag = fread($ifp, 16);
917
-        if (!is_string($tag)) {
918
-            throw new Error('Could not read input file');
919
-        }
920
-
921
-        /** @var string $subkey */
922
-        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
923
-
924
-        /** @var string $realNonce */
925
-        $realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
926
-
927
-        /** @var string $block0 */
928
-        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20(
929
-            64,
930
-            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
931
-            $subkey
932
-        );
933
-
934
-        /* Verify the Poly1305 MAC -before- attempting to decrypt! */
935
-        $state = new ParagonIE_Sodium_Core_Poly1305_State(self::substr($block0, 0, 32));
936
-        if (!self::onetimeauth_verify($state, $ifp, $tag, $mlen)) {
937
-            throw new Exception('Invalid MAC');
938
-        }
939
-
940
-        /*
894
+		fseek($ofp, $start, SEEK_SET);
895
+		fwrite($ofp, $state->finish(), ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES);
896
+		fseek($ofp, $end, SEEK_SET);
897
+		unset($state);
898
+
899
+		return true;
900
+	}
901
+
902
+	/**
903
+	 * Decrypt a file
904
+	 *
905
+	 * @param resource $ifp
906
+	 * @param resource $ofp
907
+	 * @param int $mlen
908
+	 * @param string $nonce
909
+	 * @param string $key
910
+	 * @return bool
911
+	 * @throws Error
912
+	 * @throws Exception
913
+	 */
914
+	protected static function secretbox_decrypt($ifp, $ofp, $mlen, $nonce, $key)
915
+	{
916
+		$tag = fread($ifp, 16);
917
+		if (!is_string($tag)) {
918
+			throw new Error('Could not read input file');
919
+		}
920
+
921
+		/** @var string $subkey */
922
+		$subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
923
+
924
+		/** @var string $realNonce */
925
+		$realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);
926
+
927
+		/** @var string $block0 */
928
+		$block0 = ParagonIE_Sodium_Core_Salsa20::salsa20(
929
+			64,
930
+			ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
931
+			$subkey
932
+		);
933
+
934
+		/* Verify the Poly1305 MAC -before- attempting to decrypt! */
935
+		$state = new ParagonIE_Sodium_Core_Poly1305_State(self::substr($block0, 0, 32));
936
+		if (!self::onetimeauth_verify($state, $ifp, $tag, $mlen)) {
937
+			throw new Exception('Invalid MAC');
938
+		}
939
+
940
+		/*
941 941
          * Set the cursor to the end of the first half-block. All future bytes will
942 942
          * generated from salsa20_xor_ic, starting from 1 (second block).
943 943
          */
944
-        $first32 = fread($ifp, 32);
945
-        if (!is_string($first32)) {
946
-            throw new Error('Could not read input file');
947
-        }
948
-        $first32len = self::strlen($first32);
949
-        fwrite(
950
-            $ofp,
951
-            self::xorStrings(
952
-                self::substr($block0, 32, $first32len),
953
-                self::substr($first32, 0, $first32len)
954
-            )
955
-        );
956
-        $mlen -= 32;
957
-
958
-        /** @var int $iter */
959
-        $iter = 1;
960
-
961
-        /** @var int $incr */
962
-        $incr = self::BUFFER_SIZE >> 6;
963
-
964
-        /* Decrypts ciphertext, writes to output file. */
965
-        while ($mlen > 0) {
966
-            $blockSize = $mlen > self::BUFFER_SIZE
967
-                ? self::BUFFER_SIZE
968
-                : $mlen;
969
-            $ciphertext = fread($ifp, $blockSize);
970
-            if (!is_string($ciphertext)) {
971
-                throw new Error('Could not read input file');
972
-            }
973
-            $pBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
974
-                $ciphertext,
975
-                $realNonce,
976
-                $iter,
977
-                $subkey
978
-            );
979
-            fwrite($ofp, $pBlock, $blockSize);
980
-            $mlen -= $blockSize;
981
-            $iter += $incr;
982
-        }
983
-        return true;
984
-    }
985
-
986
-    /**
987
-     * @param ParagonIE_Sodium_Core_Poly1305_State $state
988
-     * @param resource $ifp
989
-     * @param string $tag
990
-     * @param int $mlen
991
-     * @return bool
992
-     * @throws Error
993
-     */
994
-    protected static function onetimeauth_verify(ParagonIE_Sodium_Core_Poly1305_State $state, $ifp, $tag = '', $mlen = 0)
995
-    {
996
-        /** @var int $pos */
997
-        $pos = ftell($ifp);
998
-
999
-        /** @var int $iter */
1000
-        $iter = 1;
1001
-
1002
-        /** @var int $incr */
1003
-        $incr = self::BUFFER_SIZE >> 6;
1004
-
1005
-        while ($mlen > 0) {
1006
-            $blockSize = $mlen > self::BUFFER_SIZE
1007
-                ? self::BUFFER_SIZE
1008
-                : $mlen;
1009
-            $ciphertext = fread($ifp, $blockSize);
1010
-            if (!is_string($ciphertext)) {
1011
-                throw new Error('Could not read input file');
1012
-            }
1013
-            $state->update($ciphertext);
1014
-            $mlen -= $blockSize;
1015
-            $iter += $incr;
1016
-        }
1017
-        $res = ParagonIE_Sodium_Core_Util::verify_16($tag, $state->finish());
1018
-
1019
-        fseek($ifp, $pos, SEEK_SET);
1020
-        return $res;
1021
-    }
1022
-
1023
-    /**
1024
-     * Update a hash context with the contents of a file, without
1025
-     * loading the entire file into memory.
1026
-     *
1027
-     * @param resource|object $hash
1028
-     * @param resource $fp
1029
-     * @param int $size
1030
-     * @return mixed (resource on PHP < 7.2, object on PHP >= 7.2)
1031
-     * @throws Error
1032
-     * @throws TypeError
1033
-     * @psalm-suppress PossiblyInvalidArgument
1034
-     *                 PHP 7.2 changes from a resource to an object,
1035
-     *                 which causes Psalm to complain about an error.
1036
-     */
1037
-    public static function updateHashWithFile($hash, $fp, $size = 0)
1038
-    {
1039
-        /* Type checks: */
1040
-        if (PHP_VERSION_ID < 70200) {
1041
-            if (!is_resource($hash)) {
1042
-                throw new TypeError('Argument 1 must be a resource, ' . gettype($hash) . ' given.');
1043
-            }
1044
-
1045
-        } else {
1046
-            if (!is_object($hash)) {
1047
-                throw new TypeError('Argument 1 must be an object (PHP 7.2+), ' . gettype($hash) . ' given.');
1048
-            }
1049
-        }
1050
-        if (!is_resource($fp)) {
1051
-            throw new TypeError('Argument 2 must be a resource, ' . gettype($fp) . ' given.');
1052
-        }
1053
-        if (!is_int($size)) {
1054
-            throw new TypeError('Argument 3 must be an integer, ' . gettype($size) . ' given.');
1055
-        }
1056
-
1057
-        /** @var int $originalPosition */
1058
-        $originalPosition = ftell($fp);
1059
-
1060
-        // Move file pointer to beginning of file
1061
-        fseek($fp, 0, SEEK_SET);
1062
-        for ($i = 0; $i < $size; $i += self::BUFFER_SIZE) {
1063
-            /** @var string $message */
1064
-            $message = fread(
1065
-                $fp,
1066
-                ($size - $i) > self::BUFFER_SIZE
1067
-                    ? $size - $i
1068
-                    : self::BUFFER_SIZE
1069
-            );
1070
-            if (!is_string($message)) {
1071
-                throw new Error('Unexpected error reading from file.');
1072
-            }
1073
-            /** @psalm-suppress InvalidArgument */
1074
-            hash_update($hash, $message);
1075
-        }
1076
-        // Reset file pointer's position
1077
-        fseek($fp, $originalPosition, SEEK_SET);
1078
-        return $hash;
1079
-    }
944
+		$first32 = fread($ifp, 32);
945
+		if (!is_string($first32)) {
946
+			throw new Error('Could not read input file');
947
+		}
948
+		$first32len = self::strlen($first32);
949
+		fwrite(
950
+			$ofp,
951
+			self::xorStrings(
952
+				self::substr($block0, 32, $first32len),
953
+				self::substr($first32, 0, $first32len)
954
+			)
955
+		);
956
+		$mlen -= 32;
957
+
958
+		/** @var int $iter */
959
+		$iter = 1;
960
+
961
+		/** @var int $incr */
962
+		$incr = self::BUFFER_SIZE >> 6;
963
+
964
+		/* Decrypts ciphertext, writes to output file. */
965
+		while ($mlen > 0) {
966
+			$blockSize = $mlen > self::BUFFER_SIZE
967
+				? self::BUFFER_SIZE
968
+				: $mlen;
969
+			$ciphertext = fread($ifp, $blockSize);
970
+			if (!is_string($ciphertext)) {
971
+				throw new Error('Could not read input file');
972
+			}
973
+			$pBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
974
+				$ciphertext,
975
+				$realNonce,
976
+				$iter,
977
+				$subkey
978
+			);
979
+			fwrite($ofp, $pBlock, $blockSize);
980
+			$mlen -= $blockSize;
981
+			$iter += $incr;
982
+		}
983
+		return true;
984
+	}
985
+
986
+	/**
987
+	 * @param ParagonIE_Sodium_Core_Poly1305_State $state
988
+	 * @param resource $ifp
989
+	 * @param string $tag
990
+	 * @param int $mlen
991
+	 * @return bool
992
+	 * @throws Error
993
+	 */
994
+	protected static function onetimeauth_verify(ParagonIE_Sodium_Core_Poly1305_State $state, $ifp, $tag = '', $mlen = 0)
995
+	{
996
+		/** @var int $pos */
997
+		$pos = ftell($ifp);
998
+
999
+		/** @var int $iter */
1000
+		$iter = 1;
1001
+
1002
+		/** @var int $incr */
1003
+		$incr = self::BUFFER_SIZE >> 6;
1004
+
1005
+		while ($mlen > 0) {
1006
+			$blockSize = $mlen > self::BUFFER_SIZE
1007
+				? self::BUFFER_SIZE
1008
+				: $mlen;
1009
+			$ciphertext = fread($ifp, $blockSize);
1010
+			if (!is_string($ciphertext)) {
1011
+				throw new Error('Could not read input file');
1012
+			}
1013
+			$state->update($ciphertext);
1014
+			$mlen -= $blockSize;
1015
+			$iter += $incr;
1016
+		}
1017
+		$res = ParagonIE_Sodium_Core_Util::verify_16($tag, $state->finish());
1018
+
1019
+		fseek($ifp, $pos, SEEK_SET);
1020
+		return $res;
1021
+	}
1022
+
1023
+	/**
1024
+	 * Update a hash context with the contents of a file, without
1025
+	 * loading the entire file into memory.
1026
+	 *
1027
+	 * @param resource|object $hash
1028
+	 * @param resource $fp
1029
+	 * @param int $size
1030
+	 * @return mixed (resource on PHP < 7.2, object on PHP >= 7.2)
1031
+	 * @throws Error
1032
+	 * @throws TypeError
1033
+	 * @psalm-suppress PossiblyInvalidArgument
1034
+	 *                 PHP 7.2 changes from a resource to an object,
1035
+	 *                 which causes Psalm to complain about an error.
1036
+	 */
1037
+	public static function updateHashWithFile($hash, $fp, $size = 0)
1038
+	{
1039
+		/* Type checks: */
1040
+		if (PHP_VERSION_ID < 70200) {
1041
+			if (!is_resource($hash)) {
1042
+				throw new TypeError('Argument 1 must be a resource, ' . gettype($hash) . ' given.');
1043
+			}
1044
+
1045
+		} else {
1046
+			if (!is_object($hash)) {
1047
+				throw new TypeError('Argument 1 must be an object (PHP 7.2+), ' . gettype($hash) . ' given.');
1048
+			}
1049
+		}
1050
+		if (!is_resource($fp)) {
1051
+			throw new TypeError('Argument 2 must be a resource, ' . gettype($fp) . ' given.');
1052
+		}
1053
+		if (!is_int($size)) {
1054
+			throw new TypeError('Argument 3 must be an integer, ' . gettype($size) . ' given.');
1055
+		}
1056
+
1057
+		/** @var int $originalPosition */
1058
+		$originalPosition = ftell($fp);
1059
+
1060
+		// Move file pointer to beginning of file
1061
+		fseek($fp, 0, SEEK_SET);
1062
+		for ($i = 0; $i < $size; $i += self::BUFFER_SIZE) {
1063
+			/** @var string $message */
1064
+			$message = fread(
1065
+				$fp,
1066
+				($size - $i) > self::BUFFER_SIZE
1067
+					? $size - $i
1068
+					: self::BUFFER_SIZE
1069
+			);
1070
+			if (!is_string($message)) {
1071
+				throw new Error('Unexpected error reading from file.');
1072
+			}
1073
+			/** @psalm-suppress InvalidArgument */
1074
+			hash_update($hash, $message);
1075
+		}
1076
+		// Reset file pointer's position
1077
+		fseek($fp, $originalPosition, SEEK_SET);
1078
+		return $hash;
1079
+	}
1080 1080
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Util.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Util', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Poly1305.php 1 patch
Indentation   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Poly1305', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,51 +9,51 @@  discard block
 block discarded – undo
9 9
  */
10 10
 abstract class ParagonIE_Sodium_Core32_Poly1305 extends ParagonIE_Sodium_Core32_Util
11 11
 {
12
-    const BLOCK_SIZE = 16;
12
+	const BLOCK_SIZE = 16;
13 13
 
14
-    /**
15
-     * @internal You should not use this directly from another application
16
-     *
17
-     * @param string $m
18
-     * @param string $key
19
-     * @return string
20
-     */
21
-    public static function onetimeauth($m, $key)
22
-    {
23
-        if (self::strlen($key) < 32) {
24
-            throw new InvalidArgumentException(
25
-                'Key must be 32 bytes long.'
26
-            );
27
-        }
28
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
29
-            self::substr($key, 0, 32)
30
-        );
31
-        return $state
32
-            ->update($m)
33
-            ->finish();
34
-    }
14
+	/**
15
+	 * @internal You should not use this directly from another application
16
+	 *
17
+	 * @param string $m
18
+	 * @param string $key
19
+	 * @return string
20
+	 */
21
+	public static function onetimeauth($m, $key)
22
+	{
23
+		if (self::strlen($key) < 32) {
24
+			throw new InvalidArgumentException(
25
+				'Key must be 32 bytes long.'
26
+			);
27
+		}
28
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State(
29
+			self::substr($key, 0, 32)
30
+		);
31
+		return $state
32
+			->update($m)
33
+			->finish();
34
+	}
35 35
 
36
-    /**
37
-     * @internal You should not use this directly from another application
38
-     *
39
-     * @param string $mac
40
-     * @param string $m
41
-     * @param string $key
42
-     * @return bool
43
-     */
44
-    public static function onetimeauth_verify($mac, $m, $key)
45
-    {
46
-        if (self::strlen($key) < 32) {
47
-            throw new InvalidArgumentException(
48
-                'Key must be 32 bytes long.'
49
-            );
50
-        }
51
-        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
52
-            self::substr($key, 0, 32)
53
-        );
54
-        $calc = $state
55
-            ->update($m)
56
-            ->finish();
57
-        return self::verify_16($calc, $mac);
58
-    }
36
+	/**
37
+	 * @internal You should not use this directly from another application
38
+	 *
39
+	 * @param string $mac
40
+	 * @param string $m
41
+	 * @param string $key
42
+	 * @return bool
43
+	 */
44
+	public static function onetimeauth_verify($mac, $m, $key)
45
+	{
46
+		if (self::strlen($key) < 32) {
47
+			throw new InvalidArgumentException(
48
+				'Key must be 32 bytes long.'
49
+			);
50
+		}
51
+		$state = new ParagonIE_Sodium_Core32_Poly1305_State(
52
+			self::substr($key, 0, 32)
53
+		);
54
+		$calc = $state
55
+			->update($m)
56
+			->finish();
57
+		return self::verify_16($calc, $mac);
58
+	}
59 59
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Int64.php 1 patch
Indentation   +580 added lines, -580 removed lines patch added patch discarded remove patch
@@ -9,588 +9,588 @@
 block discarded – undo
9 9
  */
10 10
 class ParagonIE_Sodium_Core32_Int64
11 11
 {
12
-    /**
13
-     * @var array<int, int> - four 16-bit integers
14
-     */
15
-    public $limbs;
16
-
17
-    /**
18
-     * @var int
19
-     */
20
-    public $overflow = 0;
21
-
22
-    /**
23
-     * ParagonIE_Sodium_Core32_Int64 constructor.
24
-     * @param array $array
25
-     */
26
-    public function __construct($array = array(0, 0, 0, 0))
27
-    {
28
-        $this->limbs = array(
29
-            (int) $array[0],
30
-            (int) $array[1],
31
-            (int) $array[2],
32
-            (int) $array[3]
33
-        );
34
-        $this->overflow = 0;
35
-    }
36
-
37
-    /**
38
-     * Adds two int64 objects
39
-     *
40
-     * @param ParagonIE_Sodium_Core32_Int64 $addend
41
-     * @return ParagonIE_Sodium_Core32_Int64
42
-     */
43
-    public function addInt64(ParagonIE_Sodium_Core32_Int64 $addend)
44
-    {
45
-        $return = new ParagonIE_Sodium_Core32_Int64();
46
-        $carry = 0;
47
-        for ($i = 3; $i >= 0; --$i) {
48
-            $tmp = $this->limbs[$i] + $addend->limbs[$i] + $carry;
49
-            $carry = $tmp >> 16;
50
-            $return->limbs[$i] = (int) ($tmp & 0xffff);
51
-        }
52
-        $return->overflow = $carry;
53
-        return $return;
54
-    }
55
-
56
-    /**
57
-     * Adds a normal integer to an int64 object
58
-     *
59
-     * @param int $int
60
-     * @return ParagonIE_Sodium_Core32_Int64
61
-     */
62
-    public function addInt($int)
63
-    {
64
-        ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
65
-
66
-        $return = new ParagonIE_Sodium_Core32_Int64();
67
-        $carry = 0;
68
-        for ($i = 3; $i >= 0; --$i) {
69
-            $step = (3 - $i) << 4; // 0, 16, 32, 48
70
-            if ($i < 2) {
71
-                $toAdd = 0;
72
-            } else {
73
-                $toAdd = (($int >> $step) & 0xffff);
74
-            }
75
-            $tmp = $this->limbs[$i] + $toAdd + $carry;
76
-            $carry = $tmp >> 16;
77
-            $return->limbs[$i] = (int) ($tmp & 0xffff);
78
-        }
79
-        $return->overflow = $carry;
80
-        return $return;
81
-    }
82
-
83
-    /**
84
-     * @param int $b
85
-     * @return int
86
-     */
87
-    public function compareInt($b = 0)
88
-    {
89
-        $gt = 0;
90
-        $eq = 1;
91
-
92
-        $i = 4;
93
-        $j = 0;
94
-        while ($i > 0) {
95
-            --$i;
96
-            $x1 = $this->limbs[$i];
97
-            $x2 = ($b >> ($j << 4)) & 0xffff;
98
-            $gt |= (($x2 - $x1) >> 8) & $eq;
99
-            $eq &= (($x2 ^ $x1) - 1) >> 8;
100
-        }
101
-        return ($gt + $gt - $eq) + 1;
102
-    }
103
-
104
-    /**
105
-     * @param int $b
106
-     * @return bool
107
-     */
108
-    public function isGreaterThan($b = 0)
109
-    {
110
-        return $this->compareInt($b) > 0;
111
-    }
112
-
113
-    /**
114
-     * @param int $b
115
-     * @return bool
116
-     */
117
-    public function isLessThanInt($b = 0)
118
-    {
119
-        return $this->compareInt($b) < 0;
120
-    }
121
-
122
-
123
-    /**
124
-     * @param int $hi
125
-     * @param int $lo
126
-     * @return ParagonIE_Sodium_Core32_Int64
127
-     */
128
-    public function mask64($hi = 0, $lo = 0)
129
-    {
130
-        $a = ($hi >> 16) & 0xffff;
131
-        $b = ($hi) & 0xffff;
132
-        $c = ($lo >> 16) & 0xffff;
133
-        $d = ($lo & 0xffff);
134
-        return new ParagonIE_Sodium_Core32_Int64(
135
-            array(
136
-                $this->limbs[0] & $a,
137
-                $this->limbs[1] & $b,
138
-                $this->limbs[2] & $c,
139
-                $this->limbs[3] & $d
140
-            )
141
-        );
142
-    }
143
-
144
-    /**
145
-     * @param int $int
146
-     * @param int $size
147
-     * @return ParagonIE_Sodium_Core32_Int64
148
-     */
149
-    public function mulInt($int = 0, $size = 0)
150
-    {
151
-        ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
152
-        ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
153
-        if (!$size) {
154
-            $size = 63;
155
-        }
156
-
157
-        $a = clone $this;
158
-        $return = new ParagonIE_Sodium_Core32_Int64();
159
-
160
-        for ($i = $size; $i >= 0; --$i) {
161
-            $return = $return->addInt64(
162
-                $a->mask64(
163
-                    (int) (-($int & 1)),
164
-                    (int) (-($int & 1))
165
-                )
166
-            );
167
-            $a = $a->shiftLeft(1);
168
-            $int >>= 1;
169
-        }
170
-        return $return;
171
-    }
172
-
173
-    /**
174
-     * @param ParagonIE_Sodium_Core32_Int64 $int
175
-     * @param int $size
176
-     * @return ParagonIE_Sodium_Core32_Int64
177
-     */
178
-    public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0)
179
-    {
180
-        ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
181
-        if (!$size) {
182
-            $size = 63;
183
-        }
184
-
185
-        $a = clone $this;
186
-        $b = clone $int;
187
-        $return = new ParagonIE_Sodium_Core32_Int64();
188
-
189
-        for ($i = $size; $i >= 0; --$i) {
190
-            /*
12
+	/**
13
+	 * @var array<int, int> - four 16-bit integers
14
+	 */
15
+	public $limbs;
16
+
17
+	/**
18
+	 * @var int
19
+	 */
20
+	public $overflow = 0;
21
+
22
+	/**
23
+	 * ParagonIE_Sodium_Core32_Int64 constructor.
24
+	 * @param array $array
25
+	 */
26
+	public function __construct($array = array(0, 0, 0, 0))
27
+	{
28
+		$this->limbs = array(
29
+			(int) $array[0],
30
+			(int) $array[1],
31
+			(int) $array[2],
32
+			(int) $array[3]
33
+		);
34
+		$this->overflow = 0;
35
+	}
36
+
37
+	/**
38
+	 * Adds two int64 objects
39
+	 *
40
+	 * @param ParagonIE_Sodium_Core32_Int64 $addend
41
+	 * @return ParagonIE_Sodium_Core32_Int64
42
+	 */
43
+	public function addInt64(ParagonIE_Sodium_Core32_Int64 $addend)
44
+	{
45
+		$return = new ParagonIE_Sodium_Core32_Int64();
46
+		$carry = 0;
47
+		for ($i = 3; $i >= 0; --$i) {
48
+			$tmp = $this->limbs[$i] + $addend->limbs[$i] + $carry;
49
+			$carry = $tmp >> 16;
50
+			$return->limbs[$i] = (int) ($tmp & 0xffff);
51
+		}
52
+		$return->overflow = $carry;
53
+		return $return;
54
+	}
55
+
56
+	/**
57
+	 * Adds a normal integer to an int64 object
58
+	 *
59
+	 * @param int $int
60
+	 * @return ParagonIE_Sodium_Core32_Int64
61
+	 */
62
+	public function addInt($int)
63
+	{
64
+		ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
65
+
66
+		$return = new ParagonIE_Sodium_Core32_Int64();
67
+		$carry = 0;
68
+		for ($i = 3; $i >= 0; --$i) {
69
+			$step = (3 - $i) << 4; // 0, 16, 32, 48
70
+			if ($i < 2) {
71
+				$toAdd = 0;
72
+			} else {
73
+				$toAdd = (($int >> $step) & 0xffff);
74
+			}
75
+			$tmp = $this->limbs[$i] + $toAdd + $carry;
76
+			$carry = $tmp >> 16;
77
+			$return->limbs[$i] = (int) ($tmp & 0xffff);
78
+		}
79
+		$return->overflow = $carry;
80
+		return $return;
81
+	}
82
+
83
+	/**
84
+	 * @param int $b
85
+	 * @return int
86
+	 */
87
+	public function compareInt($b = 0)
88
+	{
89
+		$gt = 0;
90
+		$eq = 1;
91
+
92
+		$i = 4;
93
+		$j = 0;
94
+		while ($i > 0) {
95
+			--$i;
96
+			$x1 = $this->limbs[$i];
97
+			$x2 = ($b >> ($j << 4)) & 0xffff;
98
+			$gt |= (($x2 - $x1) >> 8) & $eq;
99
+			$eq &= (($x2 ^ $x1) - 1) >> 8;
100
+		}
101
+		return ($gt + $gt - $eq) + 1;
102
+	}
103
+
104
+	/**
105
+	 * @param int $b
106
+	 * @return bool
107
+	 */
108
+	public function isGreaterThan($b = 0)
109
+	{
110
+		return $this->compareInt($b) > 0;
111
+	}
112
+
113
+	/**
114
+	 * @param int $b
115
+	 * @return bool
116
+	 */
117
+	public function isLessThanInt($b = 0)
118
+	{
119
+		return $this->compareInt($b) < 0;
120
+	}
121
+
122
+
123
+	/**
124
+	 * @param int $hi
125
+	 * @param int $lo
126
+	 * @return ParagonIE_Sodium_Core32_Int64
127
+	 */
128
+	public function mask64($hi = 0, $lo = 0)
129
+	{
130
+		$a = ($hi >> 16) & 0xffff;
131
+		$b = ($hi) & 0xffff;
132
+		$c = ($lo >> 16) & 0xffff;
133
+		$d = ($lo & 0xffff);
134
+		return new ParagonIE_Sodium_Core32_Int64(
135
+			array(
136
+				$this->limbs[0] & $a,
137
+				$this->limbs[1] & $b,
138
+				$this->limbs[2] & $c,
139
+				$this->limbs[3] & $d
140
+			)
141
+		);
142
+	}
143
+
144
+	/**
145
+	 * @param int $int
146
+	 * @param int $size
147
+	 * @return ParagonIE_Sodium_Core32_Int64
148
+	 */
149
+	public function mulInt($int = 0, $size = 0)
150
+	{
151
+		ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
152
+		ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
153
+		if (!$size) {
154
+			$size = 63;
155
+		}
156
+
157
+		$a = clone $this;
158
+		$return = new ParagonIE_Sodium_Core32_Int64();
159
+
160
+		for ($i = $size; $i >= 0; --$i) {
161
+			$return = $return->addInt64(
162
+				$a->mask64(
163
+					(int) (-($int & 1)),
164
+					(int) (-($int & 1))
165
+				)
166
+			);
167
+			$a = $a->shiftLeft(1);
168
+			$int >>= 1;
169
+		}
170
+		return $return;
171
+	}
172
+
173
+	/**
174
+	 * @param ParagonIE_Sodium_Core32_Int64 $int
175
+	 * @param int $size
176
+	 * @return ParagonIE_Sodium_Core32_Int64
177
+	 */
178
+	public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0)
179
+	{
180
+		ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
181
+		if (!$size) {
182
+			$size = 63;
183
+		}
184
+
185
+		$a = clone $this;
186
+		$b = clone $int;
187
+		$return = new ParagonIE_Sodium_Core32_Int64();
188
+
189
+		for ($i = $size; $i >= 0; --$i) {
190
+			/*
191 191
             $c += (int) ($a & -($b & 1));
192 192
             $a <<= 1;
193 193
             $b >>= 1;
194 194
              */
195
-            $return = $return->addInt64(
196
-                $a->mask64(
197
-                    (int) (-($b->limbs[3] & 1)),
198
-                    (int) (-($b->limbs[3] & 1))
199
-                )
200
-            );
201
-            $a = $a->shiftLeft(1);
202
-            $b = $b->shiftRight(1);
203
-        }
204
-        return $return;
205
-    }
206
-
207
-    /**
208
-     * OR this 64-bit integer with another.
209
-     *
210
-     * @param ParagonIE_Sodium_Core32_Int64 $b
211
-     * @return ParagonIE_Sodium_Core32_Int64
212
-     */
213
-    public function orInt64(ParagonIE_Sodium_Core32_Int64 $b)
214
-    {
215
-        $return = new ParagonIE_Sodium_Core32_Int64();
216
-        $return->limbs = array(
217
-            (int) ($this->limbs[0] | $b->limbs[0]),
218
-            (int) ($this->limbs[1] | $b->limbs[1]),
219
-            (int) ($this->limbs[2] | $b->limbs[2]),
220
-            (int) ($this->limbs[3] | $b->limbs[3])
221
-        );
222
-        return $return;
223
-    }
224
-
225
-    /**
226
-     * @param int $c
227
-     * @return ParagonIE_Sodium_Core32_Int64
228
-     */
229
-    public function rotateLeft($c = 0)
230
-    {
231
-        ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
232
-
233
-        $return = new ParagonIE_Sodium_Core32_Int64();
234
-        $c &= 63;
235
-        if ($c === 0) {
236
-            // NOP, but we want a copy.
237
-            $return->limbs = $this->limbs;
238
-        } else {
239
-            $idx_shift = ($c >> 4) & 3;
240
-            $sub_shift = $c & 15;
241
-
242
-            for ($i = 3; $i >= 0; --$i) {
243
-                $j = ($i + $idx_shift) & 3;
244
-                $k = ($i + $idx_shift + 1) & 3;
245
-                $return->limbs[$i] = (int) (
246
-                    (
247
-                        ($this->limbs[$j] << $sub_shift)
248
-                            |
249
-                        ($this->limbs[$k] >> (16 - $sub_shift))
250
-                    ) & 0xffff
251
-                );
252
-            }
253
-        }
254
-        return $return;
255
-    }
256
-
257
-    /**
258
-     * Rotate to the right
259
-     *
260
-     * @param int $c
261
-     * @return ParagonIE_Sodium_Core32_Int64
262
-     */
263
-    public function rotateRight($c = 0)
264
-    {
265
-        ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
266
-
267
-        $return = new ParagonIE_Sodium_Core32_Int64();
268
-        $c &= 63;
269
-        if ($c === 0) {
270
-            // NOP, but we want a copy.
271
-            $return->limbs = $this->limbs;
272
-        } else {
273
-            $idx_shift = ($c >> 4) & 3;
274
-            $sub_shift = $c & 15;
275
-
276
-            for ($i = 3; $i >= 0; --$i) {
277
-                $j = ($i - $idx_shift) & 3;
278
-                $k = ($i - $idx_shift - 1) & 3;
279
-                $return->limbs[$i] = (int) (
280
-                    (
281
-                        ($this->limbs[$j] >> ($sub_shift))
282
-                            |
283
-                        ($this->limbs[$k] << (16 - $sub_shift))
284
-                    ) & 0xffff
285
-                );
286
-            }
287
-        }
288
-        return $return;
289
-    }
290
-    /**
291
-     * @param int $c
292
-     * @return ParagonIE_Sodium_Core32_Int64
293
-     * @throws TypeError
294
-     */
295
-    public function shiftLeft($c = 0)
296
-    {
297
-        ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
298
-        $return = new ParagonIE_Sodium_Core32_Int64();
299
-        $c &= 63;
300
-
301
-        if ($c >= 16) {
302
-            if ($c >= 48) {
303
-                $return->limbs = array(
304
-                    $this->limbs[3], 0, 0, 0
305
-                );
306
-            } elseif ($c >= 32) {
307
-                $return->limbs = array(
308
-                    $this->limbs[2], $this->limbs[3], 0, 0
309
-                );
310
-            } else {
311
-                $return->limbs = array(
312
-                    $this->limbs[1], $this->limbs[2], $this->limbs[3], 0
313
-                );
314
-            }
315
-            return $return->shiftLeft($c & 15);
316
-        }
317
-        if ($c === 0) {
318
-            $return->limbs = $this->limbs;
319
-        } elseif ($c < 0) {
320
-            return $this->shiftRight(-$c);
321
-        } else {
322
-            if (is_null($c)) {
323
-                throw new TypeError();
324
-            }
325
-            $carry = 0;
326
-            for ($i = 3; $i >= 0; --$i) {
327
-                $tmp = ($this->limbs[$i] << $c) | ($carry & 0xffff);
328
-                $return->limbs[$i] = (int) ($tmp & 0xffff);
329
-                $carry = $tmp >> 16;
330
-            }
331
-        }
332
-        return $return;
333
-    }
334
-
335
-    /**
336
-     * @param int $c
337
-     * @return ParagonIE_Sodium_Core32_Int64
338
-     * @throws TypeError
339
-     */
340
-    public function shiftRight($c = 0)
341
-    {
342
-        ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
343
-        $return = new ParagonIE_Sodium_Core32_Int64();
344
-        $c &= 63;
345
-
346
-        $negative = -(($this->limbs[0] >> 15) & 1);
347
-        if ($c >= 16) {
348
-            if ($c >= 48) {
349
-                $return->limbs = array(
350
-                    (int) ($negative & 0xffff),
351
-                    (int) ($negative & 0xffff),
352
-                    (int) ($negative & 0xffff),
353
-                    (int) $this->limbs[0]
354
-                );
355
-            } elseif ($c >= 32) {
356
-                $return->limbs = array(
357
-                    (int) ($negative & 0xffff),
358
-                    (int) ($negative & 0xffff),
359
-                    (int) $this->limbs[0],
360
-                    (int) $this->limbs[1]
361
-                );
362
-            } else {
363
-                $return->limbs = array(
364
-                    (int) ($negative & 0xffff),
365
-                    (int) $this->limbs[0],
366
-                    (int) $this->limbs[1],
367
-                    (int) $this->limbs[2]
368
-                );
369
-            }
370
-            return $return->shiftRight($c & 15);
371
-        }
372
-
373
-        if ($c === 0) {
374
-            $return->limbs = $this->limbs;
375
-        } elseif ($c < 0) {
376
-            return $this->shiftLeft(-$c);
377
-        } else {
378
-            if (is_null($c)) {
379
-                throw new TypeError();
380
-            }
381
-            $carryRight = ($negative & 0xffff);
382
-            $mask = (int) (((1 << ($c + 1)) - 1) & 0xffff);
383
-            for ($i = 0; $i < 4; ++$i) {
384
-                $return->limbs[$i] = (int) (
385
-                    (($this->limbs[$i] >> $c) | ($carryRight << (16 - $c))) & 0xffff
386
-                );
387
-                $carryRight = (int) ($this->limbs[$i] & $mask);
388
-            }
389
-        }
390
-        return $return;
391
-    }
392
-
393
-
394
-    /**
395
-     * Subtract a normal integer from an int64 object.
396
-     *
397
-     * @param int $int
398
-     * @return ParagonIE_Sodium_Core32_Int64
399
-     */
400
-    public function subInt($int)
401
-    {
402
-        ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
403
-
404
-        $return = new ParagonIE_Sodium_Core32_Int64();
405
-
406
-        $carry = 0;
407
-        for ($i = 3; $i >= 0; --$i) {
408
-            $tmp = $this->limbs[$i] - (($int >> 16) & 0xffff) + $carry;
409
-            $carry = $tmp >> 16;
410
-            $return->limbs[$i] = (int) ($tmp & 0xffff);
411
-        }
412
-        return $return;
413
-    }
414
-
415
-    /**
416
-     * The difference between two Int64 objects.
417
-     *
418
-     * @param ParagonIE_Sodium_Core32_Int64 $b
419
-     * @return ParagonIE_Sodium_Core32_Int64
420
-     */
421
-    public function subInt64(ParagonIE_Sodium_Core32_Int64 $b)
422
-    {
423
-        $return = new ParagonIE_Sodium_Core32_Int64();
424
-        $carry = 0;
425
-        for ($i = 3; $i >= 0; --$i) {
426
-            $tmp = $this->limbs[$i] - $b->limbs[$i] + $carry;
427
-            $carry = ($tmp >> 16);
428
-            $return->limbs[$i] = (int) ($tmp & 0xffff);
429
-
430
-        }
431
-        return $return;
432
-    }
433
-
434
-    /**
435
-     * XOR this 64-bit integer with another.
436
-     *
437
-     * @param ParagonIE_Sodium_Core32_Int64 $b
438
-     * @return ParagonIE_Sodium_Core32_Int64
439
-     */
440
-    public function xorInt64(ParagonIE_Sodium_Core32_Int64 $b)
441
-    {
442
-        $return = new ParagonIE_Sodium_Core32_Int64();
443
-        $return->limbs = array(
444
-            (int) ($this->limbs[0] ^ $b->limbs[0]),
445
-            (int) ($this->limbs[1] ^ $b->limbs[1]),
446
-            (int) ($this->limbs[2] ^ $b->limbs[2]),
447
-            (int) ($this->limbs[3] ^ $b->limbs[3])
448
-        );
449
-        return $return;
450
-    }
451
-
452
-    /**
453
-     * @param int $low
454
-     * @param int $high
455
-     * @return self
456
-     */
457
-    public static function fromInts($low, $high)
458
-    {
459
-        ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1);
460
-        ParagonIE_Sodium_Core32_Util::declareScalarType($high, 'int', 2);
461
-
462
-        return new ParagonIE_Sodium_Core32_Int64(
463
-            array(
464
-                (int) (($high >> 16) & 0xffff),
465
-                (int) ($high & 0xffff),
466
-                (int) (($low >> 16) & 0xffff),
467
-                (int) ($low & 0xffff)
468
-            )
469
-        );
470
-    }
471
-
472
-    /**
473
-     * @param string $string
474
-     * @return self
475
-     */
476
-    public static function fromString($string)
477
-    {
478
-        ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
479
-        $string = (string) $string;
480
-        if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
481
-            throw new RangeException(
482
-                'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
483
-            );
484
-        }
485
-        $return = new ParagonIE_Sodium_Core32_Int64();
486
-
487
-        $return->limbs[0]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8);
488
-        $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
489
-        $return->limbs[1]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8);
490
-        $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
491
-        $return->limbs[2]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff) << 8);
492
-        $return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff);
493
-        $return->limbs[3]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff) << 8);
494
-        $return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff);
495
-        return $return;
496
-    }
497
-
498
-    /**
499
-     * @param string $string
500
-     * @return self
501
-     */
502
-    public static function fromReverseString($string)
503
-    {
504
-        ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
505
-        $string = (string) $string;
506
-        if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
507
-            throw new RangeException(
508
-                'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
509
-            );
510
-        }
511
-        $return = new ParagonIE_Sodium_Core32_Int64();
512
-
513
-        $return->limbs[0]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff) << 8);
514
-        $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff);
515
-        $return->limbs[1]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff) << 8);
516
-        $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff);
517
-        $return->limbs[2]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8);
518
-        $return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
519
-        $return->limbs[3]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8);
520
-        $return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
521
-        return $return;
522
-    }
523
-
524
-    /**
525
-     * @return array<int, int>
526
-     */
527
-    public function toArray()
528
-    {
529
-        return array(
530
-            (int) ((($this->limbs[0] & 0xffff) << 16) | ($this->limbs[1] & 0xffff)),
531
-            (int) ((($this->limbs[2] & 0xffff) << 16) | ($this->limbs[3] & 0xffff))
532
-        );
533
-    }
534
-
535
-    /**
536
-     * @return ParagonIE_Sodium_Core32_Int32
537
-     */
538
-    public function toInt32()
539
-    {
540
-        $return = new ParagonIE_Sodium_Core32_Int32();
541
-        $return->limbs[0] = (int) ($this->limbs[2]);
542
-        $return->limbs[1] = (int) ($this->limbs[3]);
543
-        return $return;
544
-    }
545
-
546
-    /**
547
-     * @return ParagonIE_Sodium_Core32_Int64
548
-     */
549
-    public function toInt64()
550
-    {
551
-        $return = new ParagonIE_Sodium_Core32_Int64();
552
-        $return->limbs[0] = (int) ($this->limbs[0]);
553
-        $return->limbs[1] = (int) ($this->limbs[1]);
554
-        $return->limbs[2] = (int) ($this->limbs[2]);
555
-        $return->limbs[3] = (int) ($this->limbs[3]);
556
-        return $return;
557
-    }
558
-
559
-    /**
560
-     * @return string
561
-     */
562
-    public function toString()
563
-    {
564
-        return ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) .
565
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
566
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
567
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
568
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) .
569
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) .
570
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) .
571
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff);
572
-    }
573
-
574
-    /**
575
-     * @return string
576
-     */
577
-    public function toReverseString()
578
-    {
579
-        return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff) .
580
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) .
581
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) .
582
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) .
583
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
584
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
585
-            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
586
-            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff);
587
-    }
588
-
589
-    /**
590
-     * @return string
591
-     */
592
-    public function __toString()
593
-    {
594
-        return $this->toString();
595
-    }
195
+			$return = $return->addInt64(
196
+				$a->mask64(
197
+					(int) (-($b->limbs[3] & 1)),
198
+					(int) (-($b->limbs[3] & 1))
199
+				)
200
+			);
201
+			$a = $a->shiftLeft(1);
202
+			$b = $b->shiftRight(1);
203
+		}
204
+		return $return;
205
+	}
206
+
207
+	/**
208
+	 * OR this 64-bit integer with another.
209
+	 *
210
+	 * @param ParagonIE_Sodium_Core32_Int64 $b
211
+	 * @return ParagonIE_Sodium_Core32_Int64
212
+	 */
213
+	public function orInt64(ParagonIE_Sodium_Core32_Int64 $b)
214
+	{
215
+		$return = new ParagonIE_Sodium_Core32_Int64();
216
+		$return->limbs = array(
217
+			(int) ($this->limbs[0] | $b->limbs[0]),
218
+			(int) ($this->limbs[1] | $b->limbs[1]),
219
+			(int) ($this->limbs[2] | $b->limbs[2]),
220
+			(int) ($this->limbs[3] | $b->limbs[3])
221
+		);
222
+		return $return;
223
+	}
224
+
225
+	/**
226
+	 * @param int $c
227
+	 * @return ParagonIE_Sodium_Core32_Int64
228
+	 */
229
+	public function rotateLeft($c = 0)
230
+	{
231
+		ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
232
+
233
+		$return = new ParagonIE_Sodium_Core32_Int64();
234
+		$c &= 63;
235
+		if ($c === 0) {
236
+			// NOP, but we want a copy.
237
+			$return->limbs = $this->limbs;
238
+		} else {
239
+			$idx_shift = ($c >> 4) & 3;
240
+			$sub_shift = $c & 15;
241
+
242
+			for ($i = 3; $i >= 0; --$i) {
243
+				$j = ($i + $idx_shift) & 3;
244
+				$k = ($i + $idx_shift + 1) & 3;
245
+				$return->limbs[$i] = (int) (
246
+					(
247
+						($this->limbs[$j] << $sub_shift)
248
+							|
249
+						($this->limbs[$k] >> (16 - $sub_shift))
250
+					) & 0xffff
251
+				);
252
+			}
253
+		}
254
+		return $return;
255
+	}
256
+
257
+	/**
258
+	 * Rotate to the right
259
+	 *
260
+	 * @param int $c
261
+	 * @return ParagonIE_Sodium_Core32_Int64
262
+	 */
263
+	public function rotateRight($c = 0)
264
+	{
265
+		ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
266
+
267
+		$return = new ParagonIE_Sodium_Core32_Int64();
268
+		$c &= 63;
269
+		if ($c === 0) {
270
+			// NOP, but we want a copy.
271
+			$return->limbs = $this->limbs;
272
+		} else {
273
+			$idx_shift = ($c >> 4) & 3;
274
+			$sub_shift = $c & 15;
275
+
276
+			for ($i = 3; $i >= 0; --$i) {
277
+				$j = ($i - $idx_shift) & 3;
278
+				$k = ($i - $idx_shift - 1) & 3;
279
+				$return->limbs[$i] = (int) (
280
+					(
281
+						($this->limbs[$j] >> ($sub_shift))
282
+							|
283
+						($this->limbs[$k] << (16 - $sub_shift))
284
+					) & 0xffff
285
+				);
286
+			}
287
+		}
288
+		return $return;
289
+	}
290
+	/**
291
+	 * @param int $c
292
+	 * @return ParagonIE_Sodium_Core32_Int64
293
+	 * @throws TypeError
294
+	 */
295
+	public function shiftLeft($c = 0)
296
+	{
297
+		ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
298
+		$return = new ParagonIE_Sodium_Core32_Int64();
299
+		$c &= 63;
300
+
301
+		if ($c >= 16) {
302
+			if ($c >= 48) {
303
+				$return->limbs = array(
304
+					$this->limbs[3], 0, 0, 0
305
+				);
306
+			} elseif ($c >= 32) {
307
+				$return->limbs = array(
308
+					$this->limbs[2], $this->limbs[3], 0, 0
309
+				);
310
+			} else {
311
+				$return->limbs = array(
312
+					$this->limbs[1], $this->limbs[2], $this->limbs[3], 0
313
+				);
314
+			}
315
+			return $return->shiftLeft($c & 15);
316
+		}
317
+		if ($c === 0) {
318
+			$return->limbs = $this->limbs;
319
+		} elseif ($c < 0) {
320
+			return $this->shiftRight(-$c);
321
+		} else {
322
+			if (is_null($c)) {
323
+				throw new TypeError();
324
+			}
325
+			$carry = 0;
326
+			for ($i = 3; $i >= 0; --$i) {
327
+				$tmp = ($this->limbs[$i] << $c) | ($carry & 0xffff);
328
+				$return->limbs[$i] = (int) ($tmp & 0xffff);
329
+				$carry = $tmp >> 16;
330
+			}
331
+		}
332
+		return $return;
333
+	}
334
+
335
+	/**
336
+	 * @param int $c
337
+	 * @return ParagonIE_Sodium_Core32_Int64
338
+	 * @throws TypeError
339
+	 */
340
+	public function shiftRight($c = 0)
341
+	{
342
+		ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
343
+		$return = new ParagonIE_Sodium_Core32_Int64();
344
+		$c &= 63;
345
+
346
+		$negative = -(($this->limbs[0] >> 15) & 1);
347
+		if ($c >= 16) {
348
+			if ($c >= 48) {
349
+				$return->limbs = array(
350
+					(int) ($negative & 0xffff),
351
+					(int) ($negative & 0xffff),
352
+					(int) ($negative & 0xffff),
353
+					(int) $this->limbs[0]
354
+				);
355
+			} elseif ($c >= 32) {
356
+				$return->limbs = array(
357
+					(int) ($negative & 0xffff),
358
+					(int) ($negative & 0xffff),
359
+					(int) $this->limbs[0],
360
+					(int) $this->limbs[1]
361
+				);
362
+			} else {
363
+				$return->limbs = array(
364
+					(int) ($negative & 0xffff),
365
+					(int) $this->limbs[0],
366
+					(int) $this->limbs[1],
367
+					(int) $this->limbs[2]
368
+				);
369
+			}
370
+			return $return->shiftRight($c & 15);
371
+		}
372
+
373
+		if ($c === 0) {
374
+			$return->limbs = $this->limbs;
375
+		} elseif ($c < 0) {
376
+			return $this->shiftLeft(-$c);
377
+		} else {
378
+			if (is_null($c)) {
379
+				throw new TypeError();
380
+			}
381
+			$carryRight = ($negative & 0xffff);
382
+			$mask = (int) (((1 << ($c + 1)) - 1) & 0xffff);
383
+			for ($i = 0; $i < 4; ++$i) {
384
+				$return->limbs[$i] = (int) (
385
+					(($this->limbs[$i] >> $c) | ($carryRight << (16 - $c))) & 0xffff
386
+				);
387
+				$carryRight = (int) ($this->limbs[$i] & $mask);
388
+			}
389
+		}
390
+		return $return;
391
+	}
392
+
393
+
394
+	/**
395
+	 * Subtract a normal integer from an int64 object.
396
+	 *
397
+	 * @param int $int
398
+	 * @return ParagonIE_Sodium_Core32_Int64
399
+	 */
400
+	public function subInt($int)
401
+	{
402
+		ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
403
+
404
+		$return = new ParagonIE_Sodium_Core32_Int64();
405
+
406
+		$carry = 0;
407
+		for ($i = 3; $i >= 0; --$i) {
408
+			$tmp = $this->limbs[$i] - (($int >> 16) & 0xffff) + $carry;
409
+			$carry = $tmp >> 16;
410
+			$return->limbs[$i] = (int) ($tmp & 0xffff);
411
+		}
412
+		return $return;
413
+	}
414
+
415
+	/**
416
+	 * The difference between two Int64 objects.
417
+	 *
418
+	 * @param ParagonIE_Sodium_Core32_Int64 $b
419
+	 * @return ParagonIE_Sodium_Core32_Int64
420
+	 */
421
+	public function subInt64(ParagonIE_Sodium_Core32_Int64 $b)
422
+	{
423
+		$return = new ParagonIE_Sodium_Core32_Int64();
424
+		$carry = 0;
425
+		for ($i = 3; $i >= 0; --$i) {
426
+			$tmp = $this->limbs[$i] - $b->limbs[$i] + $carry;
427
+			$carry = ($tmp >> 16);
428
+			$return->limbs[$i] = (int) ($tmp & 0xffff);
429
+
430
+		}
431
+		return $return;
432
+	}
433
+
434
+	/**
435
+	 * XOR this 64-bit integer with another.
436
+	 *
437
+	 * @param ParagonIE_Sodium_Core32_Int64 $b
438
+	 * @return ParagonIE_Sodium_Core32_Int64
439
+	 */
440
+	public function xorInt64(ParagonIE_Sodium_Core32_Int64 $b)
441
+	{
442
+		$return = new ParagonIE_Sodium_Core32_Int64();
443
+		$return->limbs = array(
444
+			(int) ($this->limbs[0] ^ $b->limbs[0]),
445
+			(int) ($this->limbs[1] ^ $b->limbs[1]),
446
+			(int) ($this->limbs[2] ^ $b->limbs[2]),
447
+			(int) ($this->limbs[3] ^ $b->limbs[3])
448
+		);
449
+		return $return;
450
+	}
451
+
452
+	/**
453
+	 * @param int $low
454
+	 * @param int $high
455
+	 * @return self
456
+	 */
457
+	public static function fromInts($low, $high)
458
+	{
459
+		ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1);
460
+		ParagonIE_Sodium_Core32_Util::declareScalarType($high, 'int', 2);
461
+
462
+		return new ParagonIE_Sodium_Core32_Int64(
463
+			array(
464
+				(int) (($high >> 16) & 0xffff),
465
+				(int) ($high & 0xffff),
466
+				(int) (($low >> 16) & 0xffff),
467
+				(int) ($low & 0xffff)
468
+			)
469
+		);
470
+	}
471
+
472
+	/**
473
+	 * @param string $string
474
+	 * @return self
475
+	 */
476
+	public static function fromString($string)
477
+	{
478
+		ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
479
+		$string = (string) $string;
480
+		if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
481
+			throw new RangeException(
482
+				'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
483
+			);
484
+		}
485
+		$return = new ParagonIE_Sodium_Core32_Int64();
486
+
487
+		$return->limbs[0]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8);
488
+		$return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
489
+		$return->limbs[1]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8);
490
+		$return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
491
+		$return->limbs[2]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff) << 8);
492
+		$return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff);
493
+		$return->limbs[3]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff) << 8);
494
+		$return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff);
495
+		return $return;
496
+	}
497
+
498
+	/**
499
+	 * @param string $string
500
+	 * @return self
501
+	 */
502
+	public static function fromReverseString($string)
503
+	{
504
+		ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
505
+		$string = (string) $string;
506
+		if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
507
+			throw new RangeException(
508
+				'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
509
+			);
510
+		}
511
+		$return = new ParagonIE_Sodium_Core32_Int64();
512
+
513
+		$return->limbs[0]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff) << 8);
514
+		$return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff);
515
+		$return->limbs[1]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff) << 8);
516
+		$return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff);
517
+		$return->limbs[2]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8);
518
+		$return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
519
+		$return->limbs[3]  = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8);
520
+		$return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
521
+		return $return;
522
+	}
523
+
524
+	/**
525
+	 * @return array<int, int>
526
+	 */
527
+	public function toArray()
528
+	{
529
+		return array(
530
+			(int) ((($this->limbs[0] & 0xffff) << 16) | ($this->limbs[1] & 0xffff)),
531
+			(int) ((($this->limbs[2] & 0xffff) << 16) | ($this->limbs[3] & 0xffff))
532
+		);
533
+	}
534
+
535
+	/**
536
+	 * @return ParagonIE_Sodium_Core32_Int32
537
+	 */
538
+	public function toInt32()
539
+	{
540
+		$return = new ParagonIE_Sodium_Core32_Int32();
541
+		$return->limbs[0] = (int) ($this->limbs[2]);
542
+		$return->limbs[1] = (int) ($this->limbs[3]);
543
+		return $return;
544
+	}
545
+
546
+	/**
547
+	 * @return ParagonIE_Sodium_Core32_Int64
548
+	 */
549
+	public function toInt64()
550
+	{
551
+		$return = new ParagonIE_Sodium_Core32_Int64();
552
+		$return->limbs[0] = (int) ($this->limbs[0]);
553
+		$return->limbs[1] = (int) ($this->limbs[1]);
554
+		$return->limbs[2] = (int) ($this->limbs[2]);
555
+		$return->limbs[3] = (int) ($this->limbs[3]);
556
+		return $return;
557
+	}
558
+
559
+	/**
560
+	 * @return string
561
+	 */
562
+	public function toString()
563
+	{
564
+		return ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) .
565
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
566
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
567
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
568
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) .
569
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) .
570
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) .
571
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff);
572
+	}
573
+
574
+	/**
575
+	 * @return string
576
+	 */
577
+	public function toReverseString()
578
+	{
579
+		return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff) .
580
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) .
581
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) .
582
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) .
583
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
584
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
585
+			ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
586
+			ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff);
587
+	}
588
+
589
+	/**
590
+	 * @return string
591
+	 */
592
+	public function __toString()
593
+	{
594
+		return $this->toString();
595
+	}
596 596
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Ed25519.php 1 patch
Indentation   +407 added lines, -407 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Ed25519', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,410 +9,410 @@  discard block
 block discarded – undo
9 9
  */
10 10
 abstract class ParagonIE_Sodium_Core32_Ed25519 extends ParagonIE_Sodium_Core32_Curve25519
11 11
 {
12
-    const KEYPAIR_BYTES = 96;
13
-    const SEED_BYTES = 32;
14
-
15
-    /**
16
-     * @internal You should not use this directly from another application
17
-     *
18
-     * @return string (96 bytes)
19
-     */
20
-    public static function keypair()
21
-    {
22
-        $seed = random_bytes(self::SEED_BYTES);
23
-        $pk = '';
24
-        $sk = '';
25
-        self::seed_keypair($pk, $sk, $seed);
26
-        return $sk . $pk;
27
-    }
28
-
29
-    /**
30
-     * @internal You should not use this directly from another application
31
-     *
32
-     * @param string $pk
33
-     * @param string $sk
34
-     * @param string $seed
35
-     * @return string
36
-     */
37
-    public static function seed_keypair(&$pk, &$sk, $seed)
38
-    {
39
-        if (self::strlen($seed) !== self::SEED_BYTES) {
40
-            throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
41
-        }
42
-
43
-        /** @var string $pk */
44
-        $pk = self::publickey_from_secretkey($seed);
45
-        $sk = $seed . $pk;
46
-        return $sk;
47
-    }
48
-
49
-    /**
50
-     * @internal You should not use this directly from another application
51
-     *
52
-     * @param string $keypair
53
-     * @return string
54
-     */
55
-    public static function secretkey($keypair)
56
-    {
57
-        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
58
-            throw new RangeException('crypto_sign keypair must be 96 bytes long');
59
-        }
60
-        return self::substr($keypair, 0, 64);
61
-    }
62
-
63
-    /**
64
-     * @internal You should not use this directly from another application
65
-     *
66
-     * @param string $keypair
67
-     * @return string
68
-     */
69
-    public static function publickey($keypair)
70
-    {
71
-        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
72
-            throw new RangeException('crypto_sign keypair must be 96 bytes long');
73
-        }
74
-        return self::substr($keypair, 64, 32);
75
-    }
76
-
77
-    /**
78
-     * @internal You should not use this directly from another application
79
-     *
80
-     * @param string $sk
81
-     * @return string
82
-     */
83
-    public static function publickey_from_secretkey($sk)
84
-    {
85
-        /** @var string $sk */
86
-        $sk = hash('sha512', self::substr($sk, 0, 32), true);
87
-        $sk[0] = self::intToChr(
88
-            self::chrToInt($sk[0]) & 248
89
-        );
90
-        $sk[31] = self::intToChr(
91
-            (self::chrToInt($sk[31]) & 63) | 64
92
-        );
93
-        return self::sk_to_pk($sk);
94
-    }
95
-
96
-    /**
97
-     * @internal You should not use this directly from another application
98
-     *
99
-     * @param string $sk
100
-     * @return string
101
-     */
102
-    public static function sk_to_pk($sk)
103
-    {
104
-        return self::ge_p3_tobytes(
105
-            self::ge_scalarmult_base(
106
-                self::substr($sk, 0, 32)
107
-            )
108
-        );
109
-    }
110
-
111
-    /**
112
-     * @internal You should not use this directly from another application
113
-     *
114
-     * @param string $message
115
-     * @param string $sk
116
-     * @return string
117
-     */
118
-    public static function sign($message, $sk)
119
-    {
120
-        /** @var string $signature */
121
-        $signature = self::sign_detached($message, $sk);
122
-        return $signature . $message;
123
-    }
124
-
125
-    /**
126
-     * @internal You should not use this directly from another application
127
-     *
128
-     * @param string $message A signed message
129
-     * @param string $pk      Public key
130
-     * @return string         Message (without signature)
131
-     * @throws Exception
132
-     */
133
-    public static function sign_open($message, $pk)
134
-    {
135
-        /** @var string $signature */
136
-        $signature = self::substr($message, 0, 64);
137
-
138
-        /** @var string $message */
139
-        $message = self::substr($message, 64);
140
-
141
-        if (self::verify_detached($signature, $message, $pk)) {
142
-            return $message;
143
-        }
144
-        throw new Exception('Invalid signature');
145
-    }
146
-
147
-    /**
148
-     * @internal You should not use this directly from another application
149
-     *
150
-     * @param string $message
151
-     * @param string $sk
152
-     * @return string
153
-     */
154
-    public static function sign_detached($message, $sk)
155
-    {
156
-        # crypto_hash_sha512(az, sk, 32);
157
-        $az =  hash('sha512', self::substr($sk, 0, 32), true);
158
-
159
-        # az[0] &= 248;
160
-        # az[31] &= 63;
161
-        # az[31] |= 64;
162
-        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
163
-        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
164
-
165
-        # crypto_hash_sha512_init(&hs);
166
-        # crypto_hash_sha512_update(&hs, az + 32, 32);
167
-        # crypto_hash_sha512_update(&hs, m, mlen);
168
-        # crypto_hash_sha512_final(&hs, nonce);
169
-        $hs = hash_init('sha512');
170
-        hash_update($hs, self::substr($az, 32, 32));
171
-        hash_update($hs, $message);
172
-        $nonceHash = hash_final($hs, true);
173
-
174
-        # memmove(sig + 32, sk + 32, 32);
175
-        $pk = self::substr($sk, 32, 32);
176
-
177
-        # sc_reduce(nonce);
178
-        # ge_scalarmult_base(&R, nonce);
179
-        # ge_p3_tobytes(sig, &R);
180
-        $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
181
-        $sig = self::ge_p3_tobytes(
182
-            self::ge_scalarmult_base($nonce)
183
-        );
184
-
185
-        # crypto_hash_sha512_init(&hs);
186
-        # crypto_hash_sha512_update(&hs, sig, 64);
187
-        # crypto_hash_sha512_update(&hs, m, mlen);
188
-        # crypto_hash_sha512_final(&hs, hram);
189
-        $hs = hash_init('sha512');
190
-        hash_update($hs, self::substr($sig, 0, 32));
191
-        hash_update($hs, self::substr($pk, 0, 32));
192
-        hash_update($hs, $message);
193
-        $hramHash = hash_final($hs, true);
194
-
195
-        # sc_reduce(hram);
196
-        # sc_muladd(sig + 32, hram, az, nonce);
197
-        $hram = self::sc_reduce($hramHash);
198
-        $sigAfter = self::sc_muladd($hram, $az, $nonce);
199
-        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
200
-
201
-        try {
202
-            ParagonIE_Sodium_Compat::memzero($az);
203
-        } catch (Error $ex) {
204
-            $az = null;
205
-        }
206
-        return $sig;
207
-    }
208
-
209
-    /**
210
-     * @internal You should not use this directly from another application
211
-     *
212
-     * @param string $sig
213
-     * @param string $message
214
-     * @param string $pk
215
-     * @return bool
216
-     * @throws Exception
217
-     */
218
-    public static function verify_detached($sig, $message, $pk)
219
-    {
220
-        if (self::strlen($sig) < 64) {
221
-            throw new Exception('Signature is too short');
222
-        }
223
-        if (self::check_S_lt_L(self::substr($sig, 32, 32))) {
224
-            throw new Exception('S < L - Invalid signature');
225
-        }
226
-        if (self::small_order($sig)) {
227
-            throw new Exception('Signature is on too small of an order');
228
-        }
229
-        if ((self::chrToInt($sig[63]) & 224) !== 0) {
230
-            throw new Exception('Invalid signature');
231
-        }
232
-        $d = 0;
233
-        for ($i = 0; $i < 32; ++$i) {
234
-            $d |= self::chrToInt($pk[$i]);
235
-        }
236
-        if ($d === 0) {
237
-            throw new Exception('All zero public key');
238
-        }
239
-
240
-        /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
241
-        $orig = ParagonIE_Sodium_Compat::$fastMult;
242
-
243
-        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
244
-        ParagonIE_Sodium_Compat::$fastMult = true;
245
-
246
-        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */
247
-        $A = self::ge_frombytes_negate_vartime($pk);
248
-
249
-        /** @var string $hDigest */
250
-        $hDigest = hash(
251
-            'sha512',
252
-            self::substr($sig, 0, 32) .
253
-            self::substr($pk, 0, 32) .
254
-            $message,
255
-            true
256
-        );
257
-
258
-        /** @var string $h */
259
-        $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);
260
-
261
-        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */
262
-        $R = self::ge_double_scalarmult_vartime(
263
-            $h,
264
-            $A,
265
-            self::substr($sig, 32)
266
-        );
267
-
268
-        /** @var string $rcheck */
269
-        $rcheck = self::ge_tobytes($R);
270
-
271
-        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
272
-        ParagonIE_Sodium_Compat::$fastMult = $orig;
273
-
274
-        return self::verify_32($rcheck, self::substr($sig, 0, 32));
275
-    }
276
-
277
-    /**
278
-     * @internal You should not use this directly from another application
279
-     *
280
-     * @param string $S
281
-     * @return bool
282
-     * @throws Exception
283
-     */
284
-    public static function check_S_lt_L($S)
285
-    {
286
-        if (self::strlen($S) < 32) {
287
-            throw new Exception('Signature must be 32 bytes');
288
-        }
289
-        static $L = array(
290
-            0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
291
-            0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
292
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
294
-        );
295
-        $c = 0;
296
-        $n = 1;
297
-        $i = 32;
298
-
299
-        do {
300
-            --$i;
301
-            $x = self::chrToInt($S[$i]);
302
-            $c |= (
303
-                (($x - $L[$i]) >> 8) & $n
304
-            );
305
-            $n &= (
306
-                (($x ^ $L[$i]) - 1) >> 8
307
-            );
308
-        } while ($i !== 0);
309
-
310
-        return $c === 0;
311
-    }
312
-
313
-    /**
314
-     * @param string $R
315
-     * @return bool
316
-     */
317
-    public static function small_order($R)
318
-    {
319
-        static $blacklist = array(
320
-            /* 0 (order 4) */
321
-            array(
322
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
326
-            ),
327
-            /* 1 (order 1) */
328
-            array(
329
-                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
333
-            ),
334
-            /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
335
-            array(
336
-                0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
337
-                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
338
-                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
339
-                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
340
-            ),
341
-            /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
342
-            array(
343
-                0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
344
-                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
345
-                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
346
-                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
347
-            ),
348
-            /* p-1 (order 2) */
349
-            array(
350
-                0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
351
-                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
352
-                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
353
-                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
354
-            ),
355
-            /* p (order 4) */
356
-            array(
357
-                0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
358
-                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
359
-                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
360
-                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
361
-            ),
362
-            /* p+1 (order 1) */
363
-            array(
364
-                0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
365
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
366
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
367
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
368
-            ),
369
-            /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
370
-            array(
371
-                0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
372
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
373
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
374
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
375
-            ),
376
-            /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
377
-            array(
378
-                0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
379
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
380
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
381
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
382
-            ),
383
-            /* 2p-1 (order 2) */
384
-            array(
385
-                0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
386
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
387
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
388
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
389
-            ),
390
-            /* 2p (order 4) */
391
-            array(
392
-                0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
393
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
394
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
395
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
396
-            ),
397
-            /* 2p+1 (order 1) */
398
-            array(
399
-                0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
400
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
401
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
402
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
403
-            )
404
-        );
405
-        $countBlacklist = count($blacklist);
406
-
407
-        for ($i = 0; $i < $countBlacklist; ++$i) {
408
-            $c = 0;
409
-            for ($j = 0; $j < 32; ++$j) {
410
-                $c |= self::chrToInt($R[$j]) ^ $blacklist[$i][$j];
411
-            }
412
-            if ($c === 0) {
413
-                return true;
414
-            }
415
-        }
416
-        return false;
417
-    }
12
+	const KEYPAIR_BYTES = 96;
13
+	const SEED_BYTES = 32;
14
+
15
+	/**
16
+	 * @internal You should not use this directly from another application
17
+	 *
18
+	 * @return string (96 bytes)
19
+	 */
20
+	public static function keypair()
21
+	{
22
+		$seed = random_bytes(self::SEED_BYTES);
23
+		$pk = '';
24
+		$sk = '';
25
+		self::seed_keypair($pk, $sk, $seed);
26
+		return $sk . $pk;
27
+	}
28
+
29
+	/**
30
+	 * @internal You should not use this directly from another application
31
+	 *
32
+	 * @param string $pk
33
+	 * @param string $sk
34
+	 * @param string $seed
35
+	 * @return string
36
+	 */
37
+	public static function seed_keypair(&$pk, &$sk, $seed)
38
+	{
39
+		if (self::strlen($seed) !== self::SEED_BYTES) {
40
+			throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
41
+		}
42
+
43
+		/** @var string $pk */
44
+		$pk = self::publickey_from_secretkey($seed);
45
+		$sk = $seed . $pk;
46
+		return $sk;
47
+	}
48
+
49
+	/**
50
+	 * @internal You should not use this directly from another application
51
+	 *
52
+	 * @param string $keypair
53
+	 * @return string
54
+	 */
55
+	public static function secretkey($keypair)
56
+	{
57
+		if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
58
+			throw new RangeException('crypto_sign keypair must be 96 bytes long');
59
+		}
60
+		return self::substr($keypair, 0, 64);
61
+	}
62
+
63
+	/**
64
+	 * @internal You should not use this directly from another application
65
+	 *
66
+	 * @param string $keypair
67
+	 * @return string
68
+	 */
69
+	public static function publickey($keypair)
70
+	{
71
+		if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
72
+			throw new RangeException('crypto_sign keypair must be 96 bytes long');
73
+		}
74
+		return self::substr($keypair, 64, 32);
75
+	}
76
+
77
+	/**
78
+	 * @internal You should not use this directly from another application
79
+	 *
80
+	 * @param string $sk
81
+	 * @return string
82
+	 */
83
+	public static function publickey_from_secretkey($sk)
84
+	{
85
+		/** @var string $sk */
86
+		$sk = hash('sha512', self::substr($sk, 0, 32), true);
87
+		$sk[0] = self::intToChr(
88
+			self::chrToInt($sk[0]) & 248
89
+		);
90
+		$sk[31] = self::intToChr(
91
+			(self::chrToInt($sk[31]) & 63) | 64
92
+		);
93
+		return self::sk_to_pk($sk);
94
+	}
95
+
96
+	/**
97
+	 * @internal You should not use this directly from another application
98
+	 *
99
+	 * @param string $sk
100
+	 * @return string
101
+	 */
102
+	public static function sk_to_pk($sk)
103
+	{
104
+		return self::ge_p3_tobytes(
105
+			self::ge_scalarmult_base(
106
+				self::substr($sk, 0, 32)
107
+			)
108
+		);
109
+	}
110
+
111
+	/**
112
+	 * @internal You should not use this directly from another application
113
+	 *
114
+	 * @param string $message
115
+	 * @param string $sk
116
+	 * @return string
117
+	 */
118
+	public static function sign($message, $sk)
119
+	{
120
+		/** @var string $signature */
121
+		$signature = self::sign_detached($message, $sk);
122
+		return $signature . $message;
123
+	}
124
+
125
+	/**
126
+	 * @internal You should not use this directly from another application
127
+	 *
128
+	 * @param string $message A signed message
129
+	 * @param string $pk      Public key
130
+	 * @return string         Message (without signature)
131
+	 * @throws Exception
132
+	 */
133
+	public static function sign_open($message, $pk)
134
+	{
135
+		/** @var string $signature */
136
+		$signature = self::substr($message, 0, 64);
137
+
138
+		/** @var string $message */
139
+		$message = self::substr($message, 64);
140
+
141
+		if (self::verify_detached($signature, $message, $pk)) {
142
+			return $message;
143
+		}
144
+		throw new Exception('Invalid signature');
145
+	}
146
+
147
+	/**
148
+	 * @internal You should not use this directly from another application
149
+	 *
150
+	 * @param string $message
151
+	 * @param string $sk
152
+	 * @return string
153
+	 */
154
+	public static function sign_detached($message, $sk)
155
+	{
156
+		# crypto_hash_sha512(az, sk, 32);
157
+		$az =  hash('sha512', self::substr($sk, 0, 32), true);
158
+
159
+		# az[0] &= 248;
160
+		# az[31] &= 63;
161
+		# az[31] |= 64;
162
+		$az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
163
+		$az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
164
+
165
+		# crypto_hash_sha512_init(&hs);
166
+		# crypto_hash_sha512_update(&hs, az + 32, 32);
167
+		# crypto_hash_sha512_update(&hs, m, mlen);
168
+		# crypto_hash_sha512_final(&hs, nonce);
169
+		$hs = hash_init('sha512');
170
+		hash_update($hs, self::substr($az, 32, 32));
171
+		hash_update($hs, $message);
172
+		$nonceHash = hash_final($hs, true);
173
+
174
+		# memmove(sig + 32, sk + 32, 32);
175
+		$pk = self::substr($sk, 32, 32);
176
+
177
+		# sc_reduce(nonce);
178
+		# ge_scalarmult_base(&R, nonce);
179
+		# ge_p3_tobytes(sig, &R);
180
+		$nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
181
+		$sig = self::ge_p3_tobytes(
182
+			self::ge_scalarmult_base($nonce)
183
+		);
184
+
185
+		# crypto_hash_sha512_init(&hs);
186
+		# crypto_hash_sha512_update(&hs, sig, 64);
187
+		# crypto_hash_sha512_update(&hs, m, mlen);
188
+		# crypto_hash_sha512_final(&hs, hram);
189
+		$hs = hash_init('sha512');
190
+		hash_update($hs, self::substr($sig, 0, 32));
191
+		hash_update($hs, self::substr($pk, 0, 32));
192
+		hash_update($hs, $message);
193
+		$hramHash = hash_final($hs, true);
194
+
195
+		# sc_reduce(hram);
196
+		# sc_muladd(sig + 32, hram, az, nonce);
197
+		$hram = self::sc_reduce($hramHash);
198
+		$sigAfter = self::sc_muladd($hram, $az, $nonce);
199
+		$sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
200
+
201
+		try {
202
+			ParagonIE_Sodium_Compat::memzero($az);
203
+		} catch (Error $ex) {
204
+			$az = null;
205
+		}
206
+		return $sig;
207
+	}
208
+
209
+	/**
210
+	 * @internal You should not use this directly from another application
211
+	 *
212
+	 * @param string $sig
213
+	 * @param string $message
214
+	 * @param string $pk
215
+	 * @return bool
216
+	 * @throws Exception
217
+	 */
218
+	public static function verify_detached($sig, $message, $pk)
219
+	{
220
+		if (self::strlen($sig) < 64) {
221
+			throw new Exception('Signature is too short');
222
+		}
223
+		if (self::check_S_lt_L(self::substr($sig, 32, 32))) {
224
+			throw new Exception('S < L - Invalid signature');
225
+		}
226
+		if (self::small_order($sig)) {
227
+			throw new Exception('Signature is on too small of an order');
228
+		}
229
+		if ((self::chrToInt($sig[63]) & 224) !== 0) {
230
+			throw new Exception('Invalid signature');
231
+		}
232
+		$d = 0;
233
+		for ($i = 0; $i < 32; ++$i) {
234
+			$d |= self::chrToInt($pk[$i]);
235
+		}
236
+		if ($d === 0) {
237
+			throw new Exception('All zero public key');
238
+		}
239
+
240
+		/** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
241
+		$orig = ParagonIE_Sodium_Compat::$fastMult;
242
+
243
+		// Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
244
+		ParagonIE_Sodium_Compat::$fastMult = true;
245
+
246
+		/** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */
247
+		$A = self::ge_frombytes_negate_vartime($pk);
248
+
249
+		/** @var string $hDigest */
250
+		$hDigest = hash(
251
+			'sha512',
252
+			self::substr($sig, 0, 32) .
253
+			self::substr($pk, 0, 32) .
254
+			$message,
255
+			true
256
+		);
257
+
258
+		/** @var string $h */
259
+		$h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);
260
+
261
+		/** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */
262
+		$R = self::ge_double_scalarmult_vartime(
263
+			$h,
264
+			$A,
265
+			self::substr($sig, 32)
266
+		);
267
+
268
+		/** @var string $rcheck */
269
+		$rcheck = self::ge_tobytes($R);
270
+
271
+		// Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
272
+		ParagonIE_Sodium_Compat::$fastMult = $orig;
273
+
274
+		return self::verify_32($rcheck, self::substr($sig, 0, 32));
275
+	}
276
+
277
+	/**
278
+	 * @internal You should not use this directly from another application
279
+	 *
280
+	 * @param string $S
281
+	 * @return bool
282
+	 * @throws Exception
283
+	 */
284
+	public static function check_S_lt_L($S)
285
+	{
286
+		if (self::strlen($S) < 32) {
287
+			throw new Exception('Signature must be 32 bytes');
288
+		}
289
+		static $L = array(
290
+			0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
291
+			0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
292
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
294
+		);
295
+		$c = 0;
296
+		$n = 1;
297
+		$i = 32;
298
+
299
+		do {
300
+			--$i;
301
+			$x = self::chrToInt($S[$i]);
302
+			$c |= (
303
+				(($x - $L[$i]) >> 8) & $n
304
+			);
305
+			$n &= (
306
+				(($x ^ $L[$i]) - 1) >> 8
307
+			);
308
+		} while ($i !== 0);
309
+
310
+		return $c === 0;
311
+	}
312
+
313
+	/**
314
+	 * @param string $R
315
+	 * @return bool
316
+	 */
317
+	public static function small_order($R)
318
+	{
319
+		static $blacklist = array(
320
+			/* 0 (order 4) */
321
+			array(
322
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
326
+			),
327
+			/* 1 (order 1) */
328
+			array(
329
+				0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
333
+			),
334
+			/* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
335
+			array(
336
+				0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
337
+				0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
338
+				0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
339
+				0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
340
+			),
341
+			/* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
342
+			array(
343
+				0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
344
+				0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
345
+				0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
346
+				0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
347
+			),
348
+			/* p-1 (order 2) */
349
+			array(
350
+				0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
351
+				0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
352
+				0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
353
+				0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
354
+			),
355
+			/* p (order 4) */
356
+			array(
357
+				0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
358
+				0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
359
+				0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
360
+				0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
361
+			),
362
+			/* p+1 (order 1) */
363
+			array(
364
+				0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
365
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
366
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
367
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
368
+			),
369
+			/* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
370
+			array(
371
+				0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
372
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
373
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
374
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
375
+			),
376
+			/* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
377
+			array(
378
+				0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
379
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
380
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
381
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
382
+			),
383
+			/* 2p-1 (order 2) */
384
+			array(
385
+				0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
386
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
387
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
388
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
389
+			),
390
+			/* 2p (order 4) */
391
+			array(
392
+				0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
393
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
394
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
395
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
396
+			),
397
+			/* 2p+1 (order 1) */
398
+			array(
399
+				0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
400
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
401
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
402
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
403
+			)
404
+		);
405
+		$countBlacklist = count($blacklist);
406
+
407
+		for ($i = 0; $i < $countBlacklist; ++$i) {
408
+			$c = 0;
409
+			for ($j = 0; $j < 32; ++$j) {
410
+				$c |= self::chrToInt($R[$j]) ^ $blacklist[$i][$j];
411
+			}
412
+			if ($c === 0) {
413
+				return true;
414
+			}
415
+		}
416
+		return false;
417
+	}
418 418
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Poly1305/State.php 1 patch
Indentation   +418 added lines, -418 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Poly1305_State', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,421 +9,421 @@  discard block
 block discarded – undo
9 9
  */
10 10
 class ParagonIE_Sodium_Core32_Poly1305_State extends ParagonIE_Sodium_Core32_Util
11 11
 {
12
-    /**
13
-     * @var array<int, int>
14
-     */
15
-    protected $buffer = array();
16
-
17
-    /**
18
-     * @var bool
19
-     */
20
-    protected $final = false;
21
-
22
-    /**
23
-     * @var array<int, ParagonIE_Sodium_Core32_Int32>
24
-     */
25
-    public $h;
26
-
27
-    /**
28
-     * @var int
29
-     */
30
-    protected $leftover = 0;
31
-
32
-    /**
33
-     * @var array<int, ParagonIE_Sodium_Core32_Int32>
34
-     */
35
-    public $r;
36
-
37
-    /**
38
-     * @var array<int, ParagonIE_Sodium_Core32_Int64>
39
-     */
40
-    public $pad;
41
-
42
-    /**
43
-     * ParagonIE_Sodium_Core32_Poly1305_State constructor.
44
-     *
45
-     * @internal You should not use this directly from another application
46
-     *
47
-     * @param string $key
48
-     * @throws InvalidArgumentException
49
-     */
50
-    public function __construct($key = '')
51
-    {
52
-        if (self::strlen($key) < 32) {
53
-            throw new InvalidArgumentException(
54
-                'Poly1305 requires a 32-byte key'
55
-            );
56
-        }
57
-        /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
58
-        $this->r = array(
59
-            // st->r[0] = ...
60
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4))
61
-                ->mask(0x3ffffff),
62
-            // st->r[1] = ...
63
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4))
64
-                ->shiftRight(2)
65
-                ->mask(0x3ffff03),
66
-            // st->r[2] = ...
67
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4))
68
-                ->shiftRight(4)
69
-                ->mask(0x3ffc0ff),
70
-            // st->r[3] = ...
71
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4))
72
-                ->shiftRight(6)
73
-                ->mask(0x3f03fff),
74
-            // st->r[4] = ...
75
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4))
76
-                ->shiftRight(8)
77
-                ->mask(0x00fffff)
78
-        );
79
-
80
-        /* h = 0 */
81
-        $this->h = array(
82
-            new ParagonIE_Sodium_Core32_Int32(),
83
-            new ParagonIE_Sodium_Core32_Int32(),
84
-            new ParagonIE_Sodium_Core32_Int32(),
85
-            new ParagonIE_Sodium_Core32_Int32(),
86
-            new ParagonIE_Sodium_Core32_Int32()
87
-        );
88
-
89
-        /* save pad for later */
90
-        $this->pad = array(
91
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4))->toInt64(),
92
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4))->toInt64(),
93
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4))->toInt64(),
94
-            ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4))->toInt64(),
95
-        );
96
-
97
-        $this->leftover = 0;
98
-        $this->final = false;
99
-    }
100
-
101
-    /**
102
-     * @internal You should not use this directly from another application
103
-     *
104
-     * @param string $message
105
-     * @return self
106
-     */
107
-    public function update($message = '')
108
-    {
109
-        $bytes = self::strlen($message);
110
-
111
-        /* handle leftover */
112
-        if ($this->leftover) {
113
-            $want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - $this->leftover;
114
-            if ($want > $bytes) {
115
-                $want = $bytes;
116
-            }
117
-            for ($i = 0; $i < $want; ++$i) {
118
-                $mi = self::chrToInt($message[$i]);
119
-                $this->buffer[$this->leftover + $i] = $mi;
120
-            }
121
-            // We snip off the leftmost bytes.
122
-            $message = self::substr($message, $want);
123
-            $bytes = self::strlen($message);
124
-            $this->leftover += $want;
125
-            if ($this->leftover < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
126
-                // We still don't have enough to run $this->blocks()
127
-                return $this;
128
-            }
129
-
130
-            $this->blocks(
131
-                static::intArrayToString($this->buffer),
132
-                ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
133
-            );
134
-            $this->leftover = 0;
135
-        }
136
-
137
-        /* process full blocks */
138
-        if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
139
-            $want = $bytes & ~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1);
140
-            if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
141
-                $block = self::substr($message, 0, $want);
142
-                if (self::strlen($block) >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
143
-                    $this->blocks($block, $want);
144
-                    $message = self::substr($message, $want);
145
-                    $bytes = self::strlen($message);
146
-                }
147
-            }
148
-        }
149
-
150
-        /* store leftover */
151
-        if ($bytes) {
152
-            for ($i = 0; $i < $bytes; ++$i) {
153
-                $mi = self::chrToInt($message[$i]);
154
-                $this->buffer[$this->leftover + $i] = $mi;
155
-            }
156
-            $this->leftover = (int) $this->leftover + $bytes;
157
-        }
158
-        return $this;
159
-    }
160
-
161
-    /**
162
-     * @internal You should not use this directly from another application
163
-     *
164
-     * @param string $message
165
-     * @param int $bytes
166
-     * @return self
167
-     */
168
-    public function blocks($message, $bytes)
169
-    {
170
-        if (self::strlen($message) < 16) {
171
-            $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
172
-        }
173
-        $hibit = ParagonIE_Sodium_Core32_Int32::fromInt($this->final ? 0 : 1 << 24); /* 1 << 128 */
174
-        $zero = new ParagonIE_Sodium_Core32_Int64();
175
-        /**
176
-         * @var ParagonIE_Sodium_Core32_Int64 $d0
177
-         * @var ParagonIE_Sodium_Core32_Int64 $d1
178
-         * @var ParagonIE_Sodium_Core32_Int64 $d2
179
-         * @var ParagonIE_Sodium_Core32_Int64 $d3
180
-         * @var ParagonIE_Sodium_Core32_Int64 $d4
181
-         * @var ParagonIE_Sodium_Core32_Int64 $r0
182
-         * @var ParagonIE_Sodium_Core32_Int64 $r1
183
-         * @var ParagonIE_Sodium_Core32_Int64 $r2
184
-         * @var ParagonIE_Sodium_Core32_Int64 $r3
185
-         * @var ParagonIE_Sodium_Core32_Int64 $r4
186
-         *
187
-         * @var ParagonIE_Sodium_Core32_Int32 $h0
188
-         * @var ParagonIE_Sodium_Core32_Int32 $h1
189
-         * @var ParagonIE_Sodium_Core32_Int32 $h2
190
-         * @var ParagonIE_Sodium_Core32_Int32 $h3
191
-         * @var ParagonIE_Sodium_Core32_Int32 $h4
192
-         */
193
-        $r0 = $this->r[0]->toInt64();
194
-        $r1 = $this->r[1]->toInt64();
195
-        $r2 = $this->r[2]->toInt64();
196
-        $r3 = $this->r[3]->toInt64();
197
-        $r4 = $this->r[4]->toInt64();
198
-
199
-        $s1 = $r1->toInt64()->mulInt(5);
200
-        $s2 = $r2->toInt64()->mulInt(5);
201
-        $s3 = $r3->toInt64()->mulInt(5);
202
-        $s4 = $r4->toInt64()->mulInt(5);
203
-
204
-        $h0 = $this->h[0];
205
-        $h1 = $this->h[1];
206
-        $h2 = $this->h[2];
207
-        $h3 = $this->h[3];
208
-        $h4 = $this->h[4];
209
-
210
-        while ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
211
-            /* h += m[i] */
212
-            $h0 = $h0->addInt32(
213
-                ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))
214
-                    ->mask(0x3ffffff)
215
-            );
216
-            $h1 = $h1->addInt32(
217
-                ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3, 4))
218
-                    ->shiftRight(2)
219
-                    ->mask(0x3ffffff)
220
-            );
221
-            $h2 = $h2->addInt32(
222
-                ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6, 4))
223
-                    ->shiftRight(4)
224
-                    ->mask(0x3ffffff)
225
-            );
226
-            $h3 = $h3->addInt32(
227
-                ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9, 4))
228
-                    ->shiftRight(6)
229
-                    ->mask(0x3ffffff)
230
-            );
231
-            $h4 = $h4->addInt32(
232
-                ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))
233
-                    ->shiftRight(8)
234
-                    ->orInt32($hibit)
235
-            );
236
-
237
-            /* h *= r */
238
-            $d0 = $zero
239
-                ->addInt64($h0->toInt64()->mulInt64($r0))
240
-                ->addInt64($h1->toInt64()->mulInt64($s4))
241
-                ->addInt64($h2->toInt64()->mulInt64($s3))
242
-                ->addInt64($h3->toInt64()->mulInt64($s2))
243
-                ->addInt64($h4->toInt64()->mulInt64($s1));
244
-
245
-            $d1 = $zero
246
-                ->addInt64($h0->toInt64()->mulInt64($r1))
247
-                ->addInt64($h1->toInt64()->mulInt64($r0))
248
-                ->addInt64($h2->toInt64()->mulInt64($s4))
249
-                ->addInt64($h3->toInt64()->mulInt64($s3))
250
-                ->addInt64($h4->toInt64()->mulInt64($s2));
251
-
252
-            $d2 = $zero
253
-                ->addInt64($h0->toInt64()->mulInt64($r2))
254
-                ->addInt64($h1->toInt64()->mulInt64($r1))
255
-                ->addInt64($h2->toInt64()->mulInt64($r0))
256
-                ->addInt64($h3->toInt64()->mulInt64($s4))
257
-                ->addInt64($h4->toInt64()->mulInt64($s3));
258
-
259
-            $d3 = $zero
260
-                ->addInt64($h0->toInt64()->mulInt64($r3))
261
-                ->addInt64($h1->toInt64()->mulInt64($r2))
262
-                ->addInt64($h2->toInt64()->mulInt64($r1))
263
-                ->addInt64($h3->toInt64()->mulInt64($r0))
264
-                ->addInt64($h4->toInt64()->mulInt64($s4));
265
-
266
-            $d4 = $zero
267
-                ->addInt64($h0->toInt64()->mulInt64($r4))
268
-                ->addInt64($h1->toInt64()->mulInt64($r3))
269
-                ->addInt64($h2->toInt64()->mulInt64($r2))
270
-                ->addInt64($h3->toInt64()->mulInt64($r1))
271
-                ->addInt64($h4->toInt64()->mulInt64($r0));
272
-
273
-            /* (partial) h %= p */
274
-            $c = $d0->shiftRight(26);
275
-            $h0 = $d0->toInt32()->mask(0x3ffffff);
276
-            $d1 = $d1->addInt64($c);
277
-
278
-            $c = $d1->shiftRight(26);
279
-            $h1 = $d1->toInt32()->mask(0x3ffffff);
280
-            $d2 = $d2->addInt64($c);
281
-
282
-            $c = $d2->shiftRight(26);
283
-            $h2 = $d2->toInt32()->mask(0x3ffffff);
284
-            $d3 = $d3->addInt64($c);
285
-
286
-            $c = $d3->shiftRight(26);
287
-            $h3 = $d3->toInt32()->mask(0x3ffffff);
288
-            $d4 = $d4->addInt64($c);
289
-
290
-            $c = $d4->shiftRight(26);
291
-            $h4 = $d4->toInt32()->mask(0x3ffffff);
292
-            $h0 = $h0->addInt32($c->toInt32()->mulInt(5));
293
-
294
-            $c = $h0->shiftRight(26);
295
-            $h0 = $h0->mask(0x3ffffff);
296
-            $h1 = $h1->addInt32($c);
297
-
298
-            // Chop off the left 32 bytes.
299
-            $message = self::substr(
300
-                $message,
301
-                ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
302
-            );
303
-            $bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
304
-        }
305
-
306
-        /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
307
-        $this->h = array($h0, $h1, $h2, $h3, $h4);
308
-        return $this;
309
-    }
310
-
311
-    /**
312
-     * @internal You should not use this directly from another application
313
-     *
314
-     * @return string
315
-     */
316
-    public function finish()
317
-    {
318
-        /* process the remaining block */
319
-        if ($this->leftover) {
320
-            $i = $this->leftover;
321
-            $this->buffer[$i++] = 1;
322
-            for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; ++$i) {
323
-                $this->buffer[$i] = 0;
324
-            }
325
-            $this->final = true;
326
-            $this->blocks(
327
-                self::substr(
328
-                    static::intArrayToString($this->buffer),
329
-                    0,
330
-                    ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
331
-                ),
332
-                $b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
333
-            );
334
-        }
335
-
336
-        /**
337
-         * @var ParagonIE_Sodium_Core32_Int32 $f
338
-         * @var ParagonIE_Sodium_Core32_Int32 $g0
339
-         * @var ParagonIE_Sodium_Core32_Int32 $g1
340
-         * @var ParagonIE_Sodium_Core32_Int32 $g2
341
-         * @var ParagonIE_Sodium_Core32_Int32 $g3
342
-         * @var ParagonIE_Sodium_Core32_Int32 $g4
343
-         * @var ParagonIE_Sodium_Core32_Int32 $h0
344
-         * @var ParagonIE_Sodium_Core32_Int32 $h1
345
-         * @var ParagonIE_Sodium_Core32_Int32 $h2
346
-         * @var ParagonIE_Sodium_Core32_Int32 $h3
347
-         * @var ParagonIE_Sodium_Core32_Int32 $h4
348
-         */
349
-        $h0 = $this->h[0];
350
-        $h1 = $this->h[1];
351
-        $h2 = $this->h[2];
352
-        $h3 = $this->h[3];
353
-        $h4 = $this->h[4];
354
-
355
-        $c = $h1->shiftRight(26);           # $c = $h1 >> 26;
356
-        $h1 = $h1->mask(0x3ffffff);         # $h1 &= 0x3ffffff;
357
-
358
-        $h2 = $h2->addInt32($c);            # $h2 += $c;
359
-        $c = $h2->shiftRight(26);           # $c = $h2 >> 26;
360
-        $h2 = $h2->mask(0x3ffffff);         # $h2 &= 0x3ffffff;
361
-
362
-        $h3 = $h3->addInt32($c);            # $h3 += $c;
363
-        $c = $h3->shiftRight(26);           # $c = $h3 >> 26;
364
-        $h3 = $h3->mask(0x3ffffff);         # $h3 &= 0x3ffffff;
365
-
366
-        $h4 = $h4->addInt32($c);            # $h4 += $c;
367
-        $c = $h4->shiftRight(26);           # $c = $h4 >> 26;
368
-        $h4 = $h4->mask(0x3ffffff);         # $h4 &= 0x3ffffff;
369
-
370
-        $h0 = $h0->addInt32($c->mulInt(5)); # $h0 += self::mul($c, 5);
371
-        $c = $h0->shiftRight(26);           # $c = $h0 >> 26;
372
-        $h0 = $h0->mask(0x3ffffff);         # $h0 &= 0x3ffffff;
373
-        $h1 = $h1->addInt32($c);            # $h1 += $c;
374
-
375
-        /* compute h + -p */
376
-        $g0 = $h0->addInt(5);
377
-        $c  = $g0->shiftRight(26);
378
-        $g0 = $g0->mask(0x3ffffff);
379
-        $g1 = $h1->addInt32($c);
380
-        $c  = $g1->shiftRight(26);
381
-        $g1 = $g1->mask(0x3ffffff);
382
-        $g2 = $h2->addInt32($c);
383
-        $c  = $g2->shiftRight(26);
384
-        $g2 = $g2->mask(0x3ffffff);
385
-        $g3 = $h3->addInt32($c);
386
-        $c  = $g3->shiftRight(26);
387
-        $g3 = $g3->mask(0x3ffffff);
388
-        $g4 = $h4->addInt32($c)->subInt(1 << 26);
389
-
390
-        # $mask = ($g4 >> 31) - 1;
391
-        /* select h if h < p, or h + -p if h >= p */
392
-        $mask = (int) (($g4->toInt() >> 31) + 1);
393
-
394
-        $g0 = $g0->mask($mask);
395
-        $g1 = $g1->mask($mask);
396
-        $g2 = $g2->mask($mask);
397
-        $g3 = $g3->mask($mask);
398
-        $g4 = $g4->mask($mask);
399
-
400
-        $mask = (~$mask) & 0xffffffff;
401
-
402
-        $h0 = $h0->mask($mask)->orInt32($g0);
403
-        $h1 = $h1->mask($mask)->orInt32($g1);
404
-        $h2 = $h2->mask($mask)->orInt32($g2);
405
-        $h3 = $h3->mask($mask)->orInt32($g3);
406
-        $h4 = $h4->mask($mask)->orInt32($g4);
407
-
408
-        /* h = h % (2^128) */
409
-        $h0 = $h0->orInt32($h1->shiftLeft(26));
410
-        $h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20));
411
-        $h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14));
412
-        $h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8));
413
-
414
-        /* mac = (h + pad) % (2^128) */
415
-        $f = $h0->toInt64()->addInt64($this->pad[0]);
416
-        $h0 = $f->toInt32();
417
-        $f = $h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow);
418
-        $h1 = $f->toInt32();
419
-        $f = $h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow);
420
-        $h2 = $f->toInt32();
421
-        $f = $h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow);
422
-        $h3 = $f->toInt32();
423
-
424
-        return $h0->toReverseString() .
425
-            $h1->toReverseString() .
426
-            $h2->toReverseString() .
427
-            $h3->toReverseString();
428
-    }
12
+	/**
13
+	 * @var array<int, int>
14
+	 */
15
+	protected $buffer = array();
16
+
17
+	/**
18
+	 * @var bool
19
+	 */
20
+	protected $final = false;
21
+
22
+	/**
23
+	 * @var array<int, ParagonIE_Sodium_Core32_Int32>
24
+	 */
25
+	public $h;
26
+
27
+	/**
28
+	 * @var int
29
+	 */
30
+	protected $leftover = 0;
31
+
32
+	/**
33
+	 * @var array<int, ParagonIE_Sodium_Core32_Int32>
34
+	 */
35
+	public $r;
36
+
37
+	/**
38
+	 * @var array<int, ParagonIE_Sodium_Core32_Int64>
39
+	 */
40
+	public $pad;
41
+
42
+	/**
43
+	 * ParagonIE_Sodium_Core32_Poly1305_State constructor.
44
+	 *
45
+	 * @internal You should not use this directly from another application
46
+	 *
47
+	 * @param string $key
48
+	 * @throws InvalidArgumentException
49
+	 */
50
+	public function __construct($key = '')
51
+	{
52
+		if (self::strlen($key) < 32) {
53
+			throw new InvalidArgumentException(
54
+				'Poly1305 requires a 32-byte key'
55
+			);
56
+		}
57
+		/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
58
+		$this->r = array(
59
+			// st->r[0] = ...
60
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4))
61
+				->mask(0x3ffffff),
62
+			// st->r[1] = ...
63
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4))
64
+				->shiftRight(2)
65
+				->mask(0x3ffff03),
66
+			// st->r[2] = ...
67
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4))
68
+				->shiftRight(4)
69
+				->mask(0x3ffc0ff),
70
+			// st->r[3] = ...
71
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4))
72
+				->shiftRight(6)
73
+				->mask(0x3f03fff),
74
+			// st->r[4] = ...
75
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4))
76
+				->shiftRight(8)
77
+				->mask(0x00fffff)
78
+		);
79
+
80
+		/* h = 0 */
81
+		$this->h = array(
82
+			new ParagonIE_Sodium_Core32_Int32(),
83
+			new ParagonIE_Sodium_Core32_Int32(),
84
+			new ParagonIE_Sodium_Core32_Int32(),
85
+			new ParagonIE_Sodium_Core32_Int32(),
86
+			new ParagonIE_Sodium_Core32_Int32()
87
+		);
88
+
89
+		/* save pad for later */
90
+		$this->pad = array(
91
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4))->toInt64(),
92
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4))->toInt64(),
93
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4))->toInt64(),
94
+			ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4))->toInt64(),
95
+		);
96
+
97
+		$this->leftover = 0;
98
+		$this->final = false;
99
+	}
100
+
101
+	/**
102
+	 * @internal You should not use this directly from another application
103
+	 *
104
+	 * @param string $message
105
+	 * @return self
106
+	 */
107
+	public function update($message = '')
108
+	{
109
+		$bytes = self::strlen($message);
110
+
111
+		/* handle leftover */
112
+		if ($this->leftover) {
113
+			$want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - $this->leftover;
114
+			if ($want > $bytes) {
115
+				$want = $bytes;
116
+			}
117
+			for ($i = 0; $i < $want; ++$i) {
118
+				$mi = self::chrToInt($message[$i]);
119
+				$this->buffer[$this->leftover + $i] = $mi;
120
+			}
121
+			// We snip off the leftmost bytes.
122
+			$message = self::substr($message, $want);
123
+			$bytes = self::strlen($message);
124
+			$this->leftover += $want;
125
+			if ($this->leftover < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
126
+				// We still don't have enough to run $this->blocks()
127
+				return $this;
128
+			}
129
+
130
+			$this->blocks(
131
+				static::intArrayToString($this->buffer),
132
+				ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
133
+			);
134
+			$this->leftover = 0;
135
+		}
136
+
137
+		/* process full blocks */
138
+		if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
139
+			$want = $bytes & ~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1);
140
+			if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
141
+				$block = self::substr($message, 0, $want);
142
+				if (self::strlen($block) >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
143
+					$this->blocks($block, $want);
144
+					$message = self::substr($message, $want);
145
+					$bytes = self::strlen($message);
146
+				}
147
+			}
148
+		}
149
+
150
+		/* store leftover */
151
+		if ($bytes) {
152
+			for ($i = 0; $i < $bytes; ++$i) {
153
+				$mi = self::chrToInt($message[$i]);
154
+				$this->buffer[$this->leftover + $i] = $mi;
155
+			}
156
+			$this->leftover = (int) $this->leftover + $bytes;
157
+		}
158
+		return $this;
159
+	}
160
+
161
+	/**
162
+	 * @internal You should not use this directly from another application
163
+	 *
164
+	 * @param string $message
165
+	 * @param int $bytes
166
+	 * @return self
167
+	 */
168
+	public function blocks($message, $bytes)
169
+	{
170
+		if (self::strlen($message) < 16) {
171
+			$message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
172
+		}
173
+		$hibit = ParagonIE_Sodium_Core32_Int32::fromInt($this->final ? 0 : 1 << 24); /* 1 << 128 */
174
+		$zero = new ParagonIE_Sodium_Core32_Int64();
175
+		/**
176
+		 * @var ParagonIE_Sodium_Core32_Int64 $d0
177
+		 * @var ParagonIE_Sodium_Core32_Int64 $d1
178
+		 * @var ParagonIE_Sodium_Core32_Int64 $d2
179
+		 * @var ParagonIE_Sodium_Core32_Int64 $d3
180
+		 * @var ParagonIE_Sodium_Core32_Int64 $d4
181
+		 * @var ParagonIE_Sodium_Core32_Int64 $r0
182
+		 * @var ParagonIE_Sodium_Core32_Int64 $r1
183
+		 * @var ParagonIE_Sodium_Core32_Int64 $r2
184
+		 * @var ParagonIE_Sodium_Core32_Int64 $r3
185
+		 * @var ParagonIE_Sodium_Core32_Int64 $r4
186
+		 *
187
+		 * @var ParagonIE_Sodium_Core32_Int32 $h0
188
+		 * @var ParagonIE_Sodium_Core32_Int32 $h1
189
+		 * @var ParagonIE_Sodium_Core32_Int32 $h2
190
+		 * @var ParagonIE_Sodium_Core32_Int32 $h3
191
+		 * @var ParagonIE_Sodium_Core32_Int32 $h4
192
+		 */
193
+		$r0 = $this->r[0]->toInt64();
194
+		$r1 = $this->r[1]->toInt64();
195
+		$r2 = $this->r[2]->toInt64();
196
+		$r3 = $this->r[3]->toInt64();
197
+		$r4 = $this->r[4]->toInt64();
198
+
199
+		$s1 = $r1->toInt64()->mulInt(5);
200
+		$s2 = $r2->toInt64()->mulInt(5);
201
+		$s3 = $r3->toInt64()->mulInt(5);
202
+		$s4 = $r4->toInt64()->mulInt(5);
203
+
204
+		$h0 = $this->h[0];
205
+		$h1 = $this->h[1];
206
+		$h2 = $this->h[2];
207
+		$h3 = $this->h[3];
208
+		$h4 = $this->h[4];
209
+
210
+		while ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
211
+			/* h += m[i] */
212
+			$h0 = $h0->addInt32(
213
+				ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))
214
+					->mask(0x3ffffff)
215
+			);
216
+			$h1 = $h1->addInt32(
217
+				ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3, 4))
218
+					->shiftRight(2)
219
+					->mask(0x3ffffff)
220
+			);
221
+			$h2 = $h2->addInt32(
222
+				ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6, 4))
223
+					->shiftRight(4)
224
+					->mask(0x3ffffff)
225
+			);
226
+			$h3 = $h3->addInt32(
227
+				ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9, 4))
228
+					->shiftRight(6)
229
+					->mask(0x3ffffff)
230
+			);
231
+			$h4 = $h4->addInt32(
232
+				ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))
233
+					->shiftRight(8)
234
+					->orInt32($hibit)
235
+			);
236
+
237
+			/* h *= r */
238
+			$d0 = $zero
239
+				->addInt64($h0->toInt64()->mulInt64($r0))
240
+				->addInt64($h1->toInt64()->mulInt64($s4))
241
+				->addInt64($h2->toInt64()->mulInt64($s3))
242
+				->addInt64($h3->toInt64()->mulInt64($s2))
243
+				->addInt64($h4->toInt64()->mulInt64($s1));
244
+
245
+			$d1 = $zero
246
+				->addInt64($h0->toInt64()->mulInt64($r1))
247
+				->addInt64($h1->toInt64()->mulInt64($r0))
248
+				->addInt64($h2->toInt64()->mulInt64($s4))
249
+				->addInt64($h3->toInt64()->mulInt64($s3))
250
+				->addInt64($h4->toInt64()->mulInt64($s2));
251
+
252
+			$d2 = $zero
253
+				->addInt64($h0->toInt64()->mulInt64($r2))
254
+				->addInt64($h1->toInt64()->mulInt64($r1))
255
+				->addInt64($h2->toInt64()->mulInt64($r0))
256
+				->addInt64($h3->toInt64()->mulInt64($s4))
257
+				->addInt64($h4->toInt64()->mulInt64($s3));
258
+
259
+			$d3 = $zero
260
+				->addInt64($h0->toInt64()->mulInt64($r3))
261
+				->addInt64($h1->toInt64()->mulInt64($r2))
262
+				->addInt64($h2->toInt64()->mulInt64($r1))
263
+				->addInt64($h3->toInt64()->mulInt64($r0))
264
+				->addInt64($h4->toInt64()->mulInt64($s4));
265
+
266
+			$d4 = $zero
267
+				->addInt64($h0->toInt64()->mulInt64($r4))
268
+				->addInt64($h1->toInt64()->mulInt64($r3))
269
+				->addInt64($h2->toInt64()->mulInt64($r2))
270
+				->addInt64($h3->toInt64()->mulInt64($r1))
271
+				->addInt64($h4->toInt64()->mulInt64($r0));
272
+
273
+			/* (partial) h %= p */
274
+			$c = $d0->shiftRight(26);
275
+			$h0 = $d0->toInt32()->mask(0x3ffffff);
276
+			$d1 = $d1->addInt64($c);
277
+
278
+			$c = $d1->shiftRight(26);
279
+			$h1 = $d1->toInt32()->mask(0x3ffffff);
280
+			$d2 = $d2->addInt64($c);
281
+
282
+			$c = $d2->shiftRight(26);
283
+			$h2 = $d2->toInt32()->mask(0x3ffffff);
284
+			$d3 = $d3->addInt64($c);
285
+
286
+			$c = $d3->shiftRight(26);
287
+			$h3 = $d3->toInt32()->mask(0x3ffffff);
288
+			$d4 = $d4->addInt64($c);
289
+
290
+			$c = $d4->shiftRight(26);
291
+			$h4 = $d4->toInt32()->mask(0x3ffffff);
292
+			$h0 = $h0->addInt32($c->toInt32()->mulInt(5));
293
+
294
+			$c = $h0->shiftRight(26);
295
+			$h0 = $h0->mask(0x3ffffff);
296
+			$h1 = $h1->addInt32($c);
297
+
298
+			// Chop off the left 32 bytes.
299
+			$message = self::substr(
300
+				$message,
301
+				ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
302
+			);
303
+			$bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
304
+		}
305
+
306
+		/** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
307
+		$this->h = array($h0, $h1, $h2, $h3, $h4);
308
+		return $this;
309
+	}
310
+
311
+	/**
312
+	 * @internal You should not use this directly from another application
313
+	 *
314
+	 * @return string
315
+	 */
316
+	public function finish()
317
+	{
318
+		/* process the remaining block */
319
+		if ($this->leftover) {
320
+			$i = $this->leftover;
321
+			$this->buffer[$i++] = 1;
322
+			for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; ++$i) {
323
+				$this->buffer[$i] = 0;
324
+			}
325
+			$this->final = true;
326
+			$this->blocks(
327
+				self::substr(
328
+					static::intArrayToString($this->buffer),
329
+					0,
330
+					ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
331
+				),
332
+				$b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
333
+			);
334
+		}
335
+
336
+		/**
337
+		 * @var ParagonIE_Sodium_Core32_Int32 $f
338
+		 * @var ParagonIE_Sodium_Core32_Int32 $g0
339
+		 * @var ParagonIE_Sodium_Core32_Int32 $g1
340
+		 * @var ParagonIE_Sodium_Core32_Int32 $g2
341
+		 * @var ParagonIE_Sodium_Core32_Int32 $g3
342
+		 * @var ParagonIE_Sodium_Core32_Int32 $g4
343
+		 * @var ParagonIE_Sodium_Core32_Int32 $h0
344
+		 * @var ParagonIE_Sodium_Core32_Int32 $h1
345
+		 * @var ParagonIE_Sodium_Core32_Int32 $h2
346
+		 * @var ParagonIE_Sodium_Core32_Int32 $h3
347
+		 * @var ParagonIE_Sodium_Core32_Int32 $h4
348
+		 */
349
+		$h0 = $this->h[0];
350
+		$h1 = $this->h[1];
351
+		$h2 = $this->h[2];
352
+		$h3 = $this->h[3];
353
+		$h4 = $this->h[4];
354
+
355
+		$c = $h1->shiftRight(26);           # $c = $h1 >> 26;
356
+		$h1 = $h1->mask(0x3ffffff);         # $h1 &= 0x3ffffff;
357
+
358
+		$h2 = $h2->addInt32($c);            # $h2 += $c;
359
+		$c = $h2->shiftRight(26);           # $c = $h2 >> 26;
360
+		$h2 = $h2->mask(0x3ffffff);         # $h2 &= 0x3ffffff;
361
+
362
+		$h3 = $h3->addInt32($c);            # $h3 += $c;
363
+		$c = $h3->shiftRight(26);           # $c = $h3 >> 26;
364
+		$h3 = $h3->mask(0x3ffffff);         # $h3 &= 0x3ffffff;
365
+
366
+		$h4 = $h4->addInt32($c);            # $h4 += $c;
367
+		$c = $h4->shiftRight(26);           # $c = $h4 >> 26;
368
+		$h4 = $h4->mask(0x3ffffff);         # $h4 &= 0x3ffffff;
369
+
370
+		$h0 = $h0->addInt32($c->mulInt(5)); # $h0 += self::mul($c, 5);
371
+		$c = $h0->shiftRight(26);           # $c = $h0 >> 26;
372
+		$h0 = $h0->mask(0x3ffffff);         # $h0 &= 0x3ffffff;
373
+		$h1 = $h1->addInt32($c);            # $h1 += $c;
374
+
375
+		/* compute h + -p */
376
+		$g0 = $h0->addInt(5);
377
+		$c  = $g0->shiftRight(26);
378
+		$g0 = $g0->mask(0x3ffffff);
379
+		$g1 = $h1->addInt32($c);
380
+		$c  = $g1->shiftRight(26);
381
+		$g1 = $g1->mask(0x3ffffff);
382
+		$g2 = $h2->addInt32($c);
383
+		$c  = $g2->shiftRight(26);
384
+		$g2 = $g2->mask(0x3ffffff);
385
+		$g3 = $h3->addInt32($c);
386
+		$c  = $g3->shiftRight(26);
387
+		$g3 = $g3->mask(0x3ffffff);
388
+		$g4 = $h4->addInt32($c)->subInt(1 << 26);
389
+
390
+		# $mask = ($g4 >> 31) - 1;
391
+		/* select h if h < p, or h + -p if h >= p */
392
+		$mask = (int) (($g4->toInt() >> 31) + 1);
393
+
394
+		$g0 = $g0->mask($mask);
395
+		$g1 = $g1->mask($mask);
396
+		$g2 = $g2->mask($mask);
397
+		$g3 = $g3->mask($mask);
398
+		$g4 = $g4->mask($mask);
399
+
400
+		$mask = (~$mask) & 0xffffffff;
401
+
402
+		$h0 = $h0->mask($mask)->orInt32($g0);
403
+		$h1 = $h1->mask($mask)->orInt32($g1);
404
+		$h2 = $h2->mask($mask)->orInt32($g2);
405
+		$h3 = $h3->mask($mask)->orInt32($g3);
406
+		$h4 = $h4->mask($mask)->orInt32($g4);
407
+
408
+		/* h = h % (2^128) */
409
+		$h0 = $h0->orInt32($h1->shiftLeft(26));
410
+		$h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20));
411
+		$h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14));
412
+		$h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8));
413
+
414
+		/* mac = (h + pad) % (2^128) */
415
+		$f = $h0->toInt64()->addInt64($this->pad[0]);
416
+		$h0 = $f->toInt32();
417
+		$f = $h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow);
418
+		$h1 = $f->toInt32();
419
+		$f = $h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow);
420
+		$h2 = $f->toInt32();
421
+		$f = $h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow);
422
+		$h3 = $f->toInt32();
423
+
424
+		return $h0->toReverseString() .
425
+			$h1->toReverseString() .
426
+			$h2->toReverseString() .
427
+			$h3->toReverseString();
428
+	}
429 429
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Curve25519/Ge/P3.php 1 patch
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P3', false)) {
4
-    return;
4
+	return;
5 5
 }
6 6
 
7 7
 /**
@@ -9,57 +9,57 @@  discard block
 block discarded – undo
9 9
  */
10 10
 class ParagonIE_Sodium_Core32_Curve25519_Ge_P3
11 11
 {
12
-    /**
13
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
14
-     */
15
-    public $X;
12
+	/**
13
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
14
+	 */
15
+	public $X;
16 16
 
17
-    /**
18
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
19
-     */
20
-    public $Y;
17
+	/**
18
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
19
+	 */
20
+	public $Y;
21 21
 
22
-    /**
23
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
24
-     */
25
-    public $Z;
22
+	/**
23
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
24
+	 */
25
+	public $Z;
26 26
 
27
-    /**
28
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
29
-     */
30
-    public $T;
27
+	/**
28
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
29
+	 */
30
+	public $T;
31 31
 
32
-    /**
33
-     * ParagonIE_Sodium_Core32_Curve25519_Ge_P3 constructor.
34
-     *
35
-     * @internal You should not use this directly from another application
36
-     *
37
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x
38
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y
39
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z
40
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $t
41
-     */
42
-    public function __construct(
43
-        ParagonIE_Sodium_Core32_Curve25519_Fe $x = null,
44
-        ParagonIE_Sodium_Core32_Curve25519_Fe $y = null,
45
-        ParagonIE_Sodium_Core32_Curve25519_Fe $z = null,
46
-        ParagonIE_Sodium_Core32_Curve25519_Fe $t = null
47
-    ) {
48
-        if ($x === null) {
49
-            $x = new ParagonIE_Sodium_Core32_Curve25519_Fe();
50
-        }
51
-        $this->X = $x;
52
-        if ($y === null) {
53
-            $y = new ParagonIE_Sodium_Core32_Curve25519_Fe();
54
-        }
55
-        $this->Y = $y;
56
-        if ($z === null) {
57
-            $z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
58
-        }
59
-        $this->Z = $z;
60
-        if ($t === null) {
61
-            $t = new ParagonIE_Sodium_Core32_Curve25519_Fe();
62
-        }
63
-        $this->T = $t;
64
-    }
32
+	/**
33
+	 * ParagonIE_Sodium_Core32_Curve25519_Ge_P3 constructor.
34
+	 *
35
+	 * @internal You should not use this directly from another application
36
+	 *
37
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x
38
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y
39
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z
40
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $t
41
+	 */
42
+	public function __construct(
43
+		ParagonIE_Sodium_Core32_Curve25519_Fe $x = null,
44
+		ParagonIE_Sodium_Core32_Curve25519_Fe $y = null,
45
+		ParagonIE_Sodium_Core32_Curve25519_Fe $z = null,
46
+		ParagonIE_Sodium_Core32_Curve25519_Fe $t = null
47
+	) {
48
+		if ($x === null) {
49
+			$x = new ParagonIE_Sodium_Core32_Curve25519_Fe();
50
+		}
51
+		$this->X = $x;
52
+		if ($y === null) {
53
+			$y = new ParagonIE_Sodium_Core32_Curve25519_Fe();
54
+		}
55
+		$this->Y = $y;
56
+		if ($z === null) {
57
+			$z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
58
+		}
59
+		$this->Z = $z;
60
+		if ($t === null) {
61
+			$t = new ParagonIE_Sodium_Core32_Curve25519_Fe();
62
+		}
63
+		$this->T = $t;
64
+	}
65 65
 }
Please login to merge, or discard this patch.
src/library/sodium_compat/src/Core32/Curve25519/Ge/Cached.php 1 patch
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -2,64 +2,64 @@
 block discarded – undo
2 2
 
3 3
 
4 4
 if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_Cached', false)) {
5
-    return;
5
+	return;
6 6
 }
7 7
 /**
8 8
  * Class ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
9 9
  */
10 10
 class ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
11 11
 {
12
-    /**
13
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
14
-     */
15
-    public $YplusX;
12
+	/**
13
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
14
+	 */
15
+	public $YplusX;
16 16
 
17
-    /**
18
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
19
-     */
20
-    public $YminusX;
17
+	/**
18
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
19
+	 */
20
+	public $YminusX;
21 21
 
22
-    /**
23
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
24
-     */
25
-    public $Z;
22
+	/**
23
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
24
+	 */
25
+	public $Z;
26 26
 
27
-    /**
28
-     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
29
-     */
30
-    public $T2d;
27
+	/**
28
+	 * @var ParagonIE_Sodium_Core32_Curve25519_Fe
29
+	 */
30
+	public $T2d;
31 31
 
32
-    /**
33
-     * ParagonIE_Sodium_Core32_Curve25519_Ge_Cached constructor.
34
-     *
35
-     * @internal You should not use this directly from another application
36
-     *
37
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YplusX
38
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YminusX
39
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $Z
40
-     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $T2d
41
-     */
42
-    public function __construct(
43
-        ParagonIE_Sodium_Core32_Curve25519_Fe $YplusX = null,
44
-        ParagonIE_Sodium_Core32_Curve25519_Fe $YminusX = null,
45
-        ParagonIE_Sodium_Core32_Curve25519_Fe $Z = null,
46
-        ParagonIE_Sodium_Core32_Curve25519_Fe $T2d = null
47
-    ) {
48
-        if ($YplusX === null) {
49
-            $YplusX = new ParagonIE_Sodium_Core32_Curve25519_Fe();
50
-        }
51
-        $this->YplusX = $YplusX;
52
-        if ($YminusX === null) {
53
-            $YminusX = new ParagonIE_Sodium_Core32_Curve25519_Fe();
54
-        }
55
-        $this->YminusX = $YminusX;
56
-        if ($Z === null) {
57
-            $Z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
58
-        }
59
-        $this->Z = $Z;
60
-        if ($T2d === null) {
61
-            $T2d = new ParagonIE_Sodium_Core32_Curve25519_Fe();
62
-        }
63
-        $this->T2d = $T2d;
64
-    }
32
+	/**
33
+	 * ParagonIE_Sodium_Core32_Curve25519_Ge_Cached constructor.
34
+	 *
35
+	 * @internal You should not use this directly from another application
36
+	 *
37
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YplusX
38
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YminusX
39
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $Z
40
+	 * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $T2d
41
+	 */
42
+	public function __construct(
43
+		ParagonIE_Sodium_Core32_Curve25519_Fe $YplusX = null,
44
+		ParagonIE_Sodium_Core32_Curve25519_Fe $YminusX = null,
45
+		ParagonIE_Sodium_Core32_Curve25519_Fe $Z = null,
46
+		ParagonIE_Sodium_Core32_Curve25519_Fe $T2d = null
47
+	) {
48
+		if ($YplusX === null) {
49
+			$YplusX = new ParagonIE_Sodium_Core32_Curve25519_Fe();
50
+		}
51
+		$this->YplusX = $YplusX;
52
+		if ($YminusX === null) {
53
+			$YminusX = new ParagonIE_Sodium_Core32_Curve25519_Fe();
54
+		}
55
+		$this->YminusX = $YminusX;
56
+		if ($Z === null) {
57
+			$Z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
58
+		}
59
+		$this->Z = $Z;
60
+		if ($T2d === null) {
61
+			$T2d = new ParagonIE_Sodium_Core32_Curve25519_Fe();
62
+		}
63
+		$this->T2d = $T2d;
64
+	}
65 65
 }
Please login to merge, or discard this patch.