Completed
Push — develop ( f0d100...266ee2 )
by J.D.
04:14
created

ParagonIE_Sodium_Crypto32   D

Complexity

Total Complexity 64

Size/Duplication

Total Lines 1160
Duplicated Lines 57.16 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
dl 663
loc 1160
rs 4.8327
c 0
b 0
f 0
wmc 64
lcom 1
cbo 11

34 Methods

Rating   Name   Duplication   Size   Complexity  
A aead_chacha20poly1305_decrypt() 58 58 3
B aead_chacha20poly1305_encrypt() 39 39 2
A aead_chacha20poly1305_ietf_decrypt() 64 64 3
B aead_chacha20poly1305_ietf_encrypt() 41 41 2
A aead_xchacha20poly1305_ietf_decrypt() 15 15 1
A aead_xchacha20poly1305_ietf_encrypt() 15 15 1
A auth() 0 8 1
A auth_verify() 0 7 1
A box() 12 12 1
B box_seal() 34 34 2
B box_seal_open() 37 37 2
A box_beforenm() 0 7 1
A box_keypair() 0 6 1
A box_keypair_from_secretkey_and_publickey() 0 5 1
A box_secretkey() 0 7 2
A box_publickey() 7 7 2
A box_publickey_from_secretkey() 0 7 2
A box_open() 0 11 1
B generichash() 29 29 3
A generichash_final() 17 17 2
A generichash_init() 18 18 3
A generichash_update() 15 15 1
A keyExchange() 0 8 1
A scalarmult() 0 6 1
A scalarmult_base() 0 6 1
A scalarmult_throw_if_zero() 12 12 3
B secretbox() 62 62 4
B secretbox_open() 60 60 4
B secretbox_xchacha20poly1305() 66 66 4
B secretbox_xchacha20poly1305_open() 62 62 4
A sign_detached() 0 4 1
A sign() 0 4 1
A sign_open() 0 4 1
A sign_verify_detached() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ParagonIE_Sodium_Crypto32 often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ParagonIE_Sodium_Crypto32, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
if (class_exists('ParagonIE_Sodium_Crypto32', false)) {
4
    return;
5
}
6
7
/**
8
 * Class ParagonIE_Sodium_Crypto
9
 *
10
 * ATTENTION!
11
 *
12
 * If you are using this library, you should be using
13
 * ParagonIE_Sodium_Compat in your code, not this class.
14
 */
15
abstract class ParagonIE_Sodium_Crypto32
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 View Code Duplication
    public static function aead_chacha20poly1305_decrypt(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
107
            $block0 = null;
0 ignored issues
show
Unused Code introduced by
$block0 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function aead_chacha20poly1305_encrypt(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
162
            $block0 = null;
0 ignored issues
show
Unused Code introduced by
$block0 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function aead_chacha20poly1305_ietf_decrypt(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
233
            $block0 = null;
0 ignored issues
show
Unused Code introduced by
$block0 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function aead_chacha20poly1305_ietf_encrypt(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
290
            $block0 = null;
0 ignored issues
show
Unused Code introduced by
$block0 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function aead_xchacha20poly1305_ietf_decrypt(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function aead_xchacha20poly1305_ietf_encrypt(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function box($plaintext, $nonce, $keypair)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function box_seal($message, $publicKey)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
461
            $ephemeralKeypair = null;
0 ignored issues
show
Unused Code introduced by
$ephemeralKeypair is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
462
            $ephemeralSK = null;
0 ignored issues
show
Unused Code introduced by
$ephemeralSK is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
463
            $nonce = null;
0 ignored issues
show
Unused Code introduced by
$nonce is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function box_seal_open($message, $keypair)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
508
            $secretKey = null;
0 ignored issues
show
Unused Code introduced by
$secretKey is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
509
            $ephemeralPK = null;
0 ignored issues
show
Unused Code introduced by
$ephemeralPK is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
510
            $nonce = null;
0 ignored issues
show
Unused Code introduced by
$nonce is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function box_publickey($keypair)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function generichash($message, $key = '', $outlen = 32)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function generichash_final($ctx, $outlen = 32)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function generichash_init($key = '', $outputLength = 32)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function generichash_update($ctx, $message)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    protected static function scalarmult_throw_if_zero($q)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public static function secretbox($plaintext, $nonce, $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
882
            $block0 = null;
0 ignored issues
show
Unused Code introduced by
$block0 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
883
            $subkey = null;
0 ignored issues
show
Unused Code introduced by
$subkey is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function secretbox_open($ciphertext, $nonce, $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
942
                $subkey = null;
0 ignored issues
show
Unused Code introduced by
$subkey is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1031
            $block0 = null;
0 ignored issues
show
Unused Code introduced by
$block0 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1032
            $subkey = null;
0 ignored issues
show
Unused Code introduced by
$subkey is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 View Code Duplication
    public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1092
                $subkey = null;
0 ignored issues
show
Unused Code introduced by
$subkey is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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
}
1175