Test Failed
Push — main ( 57b19c...1fe2cd )
by Dimitri
15:57
created

OpenSSLHandler::encrypt()   B

Complexity

Conditions 8
Paths 35

Size

Total Lines 31
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 13
c 1
b 0
f 0
nc 35
nop 2
dl 0
loc 31
ccs 0
cts 10
cp 0
crap 72
rs 8.4444
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\Security\Encryption\Handlers;
13
14
use BlitzPHP\Exceptions\EncryptionException;
15
16
/**
17
 * Gestionnaire de chiffrement basé sur la librairie OpenSSL
18
 *
19
 * @credit <a href="http://www.codeigniter.com">CodeIgniter 4.4 - \CodeIgniter\Encryption\Handlers\OpenSSLHandler</a>
20
 */
21
class OpenSSLHandler extends BaseHandler
22
{
23
    /**
24
     * HMAC digest à utiliser
25
     */
26
    protected string $digest = 'SHA512';
27
28
    /**
29
     * Liste des algorithmes HMAC pris en charge
30
     *
31
     * @var array [name => digest size]
32
     */
33
    protected array $digestSize = [
34
        'SHA224' => 28,
35
        'SHA256' => 32,
36
        'SHA384' => 48,
37
        'SHA512' => 64,
38
    ];
39
40
    /**
41
     * Chiffrement à utiliser
42
     */
43
    protected string $cipher = 'AES-256-CTR';
44
45
    /**
46
     * Indique si le texte chiffré doit être brut. S'il est défini sur false, il sera codé en base64.
47
     */
48
    protected bool $rawData = true;
49
50
    /**
51
     * Informations sur la clé de cryptage.
52
     * Ce paramètre est uniquement utilisé par OpenSSLHandler.
53
     */
54
    public string $encryptKeyInfo = '';
55
56
    /**
57
     * Informations sur la clé d'authentification.
58
     * Ce paramètre est uniquement utilisé par OpenSSLHandler.
59
     */
60
    public string $authKeyInfo = '';
61
62
    /**
63
     * {@inheritDoc}
64
     */
65
    public function encrypt(string $data, null|array|string $params = null): string
66
    {
67
        // Autoriser le remplacement de clé
68
        if ($params) {
69
            $this->key = is_array($params) && isset($params['key']) ? $params['key'] : $params;
70
        }
71
72
        if (empty($this->key)) {
73
            throw EncryptionException::needsStarterKey();
74
        }
75
76
        // derive a secret key
77
        $encryptKey = \hash_hkdf($this->digest, $this->key, 0, $this->encryptKeyInfo);
78
79
        // cryptage de base
80
        $iv = ($ivSize = \openssl_cipher_iv_length($this->cipher)) ? \openssl_random_pseudo_bytes($ivSize) : null;
81
82
        $data = \openssl_encrypt($data, $this->cipher, $encryptKey, OPENSSL_RAW_DATA, $iv);
0 ignored issues
show
Bug introduced by
It seems like $iv can also be of type null; however, parameter $iv of openssl_encrypt() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
        $data = \openssl_encrypt($data, $this->cipher, $encryptKey, OPENSSL_RAW_DATA, /** @scrutinizer ignore-type */ $iv);
Loading history...
83
84
        if ($data === false) {
85
            throw EncryptionException::encryptionFailed();
86
        }
87
88
        $result = $this->rawData ? $iv . $data : base64_encode($iv . $data);
89
90
        // dériver une clé secrète
91
        $authKey = \hash_hkdf($this->digest, $this->key, 0, $this->authKeyInfo);
92
93
        $hmacKey = \hash_hmac($this->digest, $result, $authKey, $this->rawData);
94
95
        return $hmacKey . $result;
96
    }
97
98
    /**
99
     * {@inheritDoc}
100
     */
101
    public function decrypt(string $data, null|array|string $params = null): string
102
    {
103
        // Autoriser le remplacement de clé
104
        if ($params) {
105
            $this->key = is_array($params) && isset($params['key']) ? $params['key'] : $params;
106
        }
107
108
        if (empty($this->key)) {
109
            throw EncryptionException::needsStarterKey();
110
        }
111
112
        // dériver une clé secrète
113
        $authKey = \hash_hkdf($this->digest, $this->key, 0, $this->authKeyInfo);
114
115
        $hmacLength = $this->rawData
116
            ? $this->digestSize[$this->digest]
117
            : $this->digestSize[$this->digest] * 2;
118
119
        $hmacKey  = self::substr($data, 0, $hmacLength);
120
        $data     = self::substr($data, $hmacLength);
121
        $hmacCalc = \hash_hmac($this->digest, $data, $authKey, $this->rawData);
122
123
        if (! hash_equals($hmacKey, $hmacCalc)) {
124
            throw EncryptionException::authenticationFailed();
125
        }
126
127
        $data = $this->rawData ? $data : base64_decode($data, true);
128
129
        if ($ivSize = \openssl_cipher_iv_length($this->cipher)) {
130
            $iv   = self::substr($data, 0, $ivSize);
131
            $data = self::substr($data, $ivSize);
132
        } else {
133
            $iv = null;
134
        }
135
136
        // dériver une clé secrète
137
        $encryptKey = \hash_hkdf($this->digest, $this->key, 0, $this->encryptKeyInfo);
138
139
        return \openssl_decrypt($data, $this->cipher, $encryptKey, OPENSSL_RAW_DATA, $iv);
0 ignored issues
show
Bug introduced by
It seems like $iv can also be of type null; however, parameter $iv of openssl_decrypt() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

139
        return \openssl_decrypt($data, $this->cipher, $encryptKey, OPENSSL_RAW_DATA, /** @scrutinizer ignore-type */ $iv);
Loading history...
140
    }
141
}
142