Passed
Push — main ( d71b68...a743f7 )
by Dimitri
08:12 queued 04:09
created

Encryption::encrypt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
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;
13
14
use BlitzPHP\Contracts\Security\EncrypterInterface;
15
use BlitzPHP\Exceptions\EncryptionException;
16
17
/**
18
 * Gestionnaire de chiffrement BlitzPHP
19
 *
20
 * Fournit un cryptage à clé bidirectionnel via les extensions PHP Sodium et/ou OpenSSL.
21
 * Cette classe détermine le pilote, le chiffrement et le mode à utiliser, puis initialise le gestionnaire de chiffrement approprié.
22
 *
23
 * @credit <a href="http://www.codeigniter.com">CodeIgniter 4.4 - \CodeIgniter\Encryption\Encryption</a>
24
 */
25
class Encryption implements EncrypterInterface
26
{
27
    /**
28
     * Le chiffreur que nous créons
29
     */
30
    protected ?EncrypterInterface $encrypter = null;
31
32
    /**
33
     * Le pilote utilisé
34
     */
35
    protected string $driver = '';
36
37
    /**
38
     * The key/seed being used
39
     */
40
    protected string $key = '';
41
42
    /**
43
     * La clé HMAC dérivée
44
     */
45
    protected string $hmacKey;
46
47
    /**
48
     * HMAC digest à utiliser
49
     */
50
    protected string $digest = 'SHA512';
51
52
    /**
53
     * Pilotes aux classes de gestionnaires, par ordre de préférence
54
     */
55
    protected array $drivers = [
56
        'OpenSSL',
57
        'Sodium',
58
    ];
59
60
    /**
61
     * Gestionnaires à installer
62
     *
63
     * @var array<string, bool>
64
     */
65
    protected array $handlers = [];
66
67
    /**
68
     * @throws EncryptionException
69
     */
70
    public function __construct(protected ?object $config = null)
71
    {
72 10
        $config ??= (object) config('encryption');
73
74 10
        $this->config = $config;
75 10
        $this->key    = $config->key;
0 ignored issues
show
Bug introduced by
The property key does not seem to exist on BlitzPHP\Config\Config.
Loading history...
76 10
        $this->driver = $config->driver;
0 ignored issues
show
Bug introduced by
The property driver does not seem to exist on BlitzPHP\Config\Config.
Loading history...
77 10
        $this->digest = $config->digest ?? 'SHA512';
0 ignored issues
show
Bug introduced by
The property digest does not seem to exist on BlitzPHP\Config\Config.
Loading history...
78
79
        $this->handlers = [
80
            'OpenSSL' => extension_loaded('openssl'),
81
            // le SodiumHandler utilise une API (comme sodium_pad) qui n'est disponible que sur la version 1.0.14+
82
            'Sodium' => extension_loaded('sodium') && version_compare(SODIUM_LIBRARY_VERSION, '1.0.14', '>='),
83 10
        ];
84
85
        if (! in_array($this->driver, $this->drivers, true) || (array_key_exists($this->driver, $this->handlers) && ! $this->handlers[$this->driver])) {
86 10
            throw EncryptionException::noHandlerAvailable($this->driver);
87
        }
88
    }
89
90
    /**
91
     * {@inheritDoc}
92
     */
93
    public function encrypt(string $data, null|array|string $params = null): string
94
    {
95 2
        return $this->encrypter()->encrypt($data, $params);
96
    }
97
98
    /**
99
     * {@inheritDoc}
100
     */
101
    public function decrypt(string $data, null|array|string $params = null): string
102
    {
103 2
        return $this->encrypter()->decrypt($data, $params);
104
    }
105
106
    /**
107
     * {@inheritDoc}
108
     */
109
    public function getKey(): string
110
    {
111 2
        return $this->encrypter()->getKey();
112
    }
113
114
    /**
115
     * Initialiser ou réinitialiser un chiffreur
116
     *
117
     * @throws EncryptionException
118
     */
119
    public function initialize(?object $config = null): EncrypterInterface
120
    {
121
        if ($config) {
122 8
            $this->key    = $config->key;
123 8
            $this->driver = $config->driver;
124 8
            $this->digest = $config->digest ?? 'SHA512';
125
        }
126
127
        if ($this->driver === '') {
128 2
            throw EncryptionException::noDriverRequested();
129
        }
130
131
        if (! in_array($this->driver, $this->drivers, true)) {
132 2
            throw EncryptionException::unKnownHandler($this->driver);
133
        }
134
135
        if ($this->key === '' || $this->key === '0') {
136 4
            throw EncryptionException::needsStarterKey();
137
        }
138
139 6
        $this->hmacKey = bin2hex(\hash_hkdf($this->digest, $this->key));
140
141 6
        $handlerName     = 'BlitzPHP\\Security\\Encryption\\Handlers\\' . $this->driver . 'Handler';
142 6
        $this->encrypter = new $handlerName($config);
143
144 6
        return $this->encrypter;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->encrypter could return the type null which is incompatible with the type-hinted return BlitzPHP\Contracts\Security\EncrypterInterface. Consider adding an additional type-check to rule them out.
Loading history...
145
    }
146
147
    /**
148
     * Créer une clé aléatoire
149
     */
150
    public static function createKey(int $length = 32): string
151
    {
152 2
        return random_bytes($length);
153
    }
154
155
    /**
156
     * Fourni un accès en lecture seule à certaines de nos propriétés
157
     *
158
     * @param string $key Nom de la propriete
159
     *
160
     * @return array|bool|int|string|null
161
     */
162
    public function __get($key)
163
    {
164
        if ($this->__isset($key)) {
165 4
            return $this->{$key};
166
        }
167
168 2
        return null;
169
    }
170
171
    /**
172
     * Assure la vérification de certaines de nos propriétés
173
     *
174
     * @param string $key Nom de la propriete
175
     */
176
    public function __isset($key): bool
177
    {
178 4
        return in_array($key, ['key', 'digest', 'driver', 'drivers'], true);
179
    }
180
181
    private function encrypter(): EncrypterInterface
182
    {
183
        if (null === $this->encrypter) {
184 2
            $this->encrypter = $this->initialize($this->config);
185
        }
186
187 2
        return $this->encrypter;
188
    }
189
}
190