ci4
176 строк · 4.2 Кб
1<?php
2
3declare(strict_types=1);
4
5/**
6* This file is part of CodeIgniter 4 framework.
7*
8* (c) CodeIgniter Foundation <admin@codeigniter.com>
9*
10* For the full copyright and license information, please view
11* the LICENSE file that was distributed with this source code.
12*/
13
14namespace CodeIgniter\Encryption;
15
16use CodeIgniter\Encryption\Exceptions\EncryptionException;
17use Config\Encryption as EncryptionConfig;
18
19/**
20* CodeIgniter Encryption Manager
21*
22* Provides two-way keyed encryption via PHP's Sodium and/or OpenSSL extensions.
23* This class determines the driver, cipher, and mode to use, and then
24* initializes the appropriate encryption handler.
25*
26* @see \CodeIgniter\Encryption\EncryptionTest
27*/
28class Encryption
29{
30/**
31* The encrypter we create
32*
33* @var EncrypterInterface
34*/
35protected $encrypter;
36
37/**
38* The driver being used
39*
40* @var string
41*/
42protected $driver;
43
44/**
45* The key/seed being used
46*
47* @var string
48*/
49protected $key;
50
51/**
52* The derived HMAC key
53*
54* @var string
55*/
56protected $hmacKey;
57
58/**
59* HMAC digest to use
60*
61* @var string
62*/
63protected $digest = 'SHA512';
64
65/**
66* Map of drivers to handler classes, in preference order
67*
68* @var array
69*/
70protected $drivers = [
71'OpenSSL',
72'Sodium',
73];
74
75/**
76* Handlers that are to be installed
77*
78* @var array<string, bool>
79*/
80protected $handlers = [];
81
82/**
83* @throws EncryptionException
84*/
85public function __construct(?EncryptionConfig $config = null)
86{
87$config ??= new EncryptionConfig();
88
89$this->key = $config->key;
90$this->driver = $config->driver;
91$this->digest = $config->digest ?? 'SHA512';
92
93$this->handlers = [
94'OpenSSL' => extension_loaded('openssl'),
95// the SodiumHandler uses some API (like sodium_pad) that is available only on v1.0.14+
96'Sodium' => extension_loaded('sodium') && version_compare(SODIUM_LIBRARY_VERSION, '1.0.14', '>='),
97];
98
99if (! in_array($this->driver, $this->drivers, true) || (array_key_exists($this->driver, $this->handlers) && ! $this->handlers[$this->driver])) {
100throw EncryptionException::forNoHandlerAvailable($this->driver);
101}
102}
103
104/**
105* Initialize or re-initialize an encrypter
106*
107* @return EncrypterInterface
108*
109* @throws EncryptionException
110*/
111public function initialize(?EncryptionConfig $config = null)
112{
113if ($config instanceof EncryptionConfig) {
114$this->key = $config->key;
115$this->driver = $config->driver;
116$this->digest = $config->digest ?? 'SHA512';
117}
118
119if (empty($this->driver)) {
120throw EncryptionException::forNoDriverRequested();
121}
122
123if (! in_array($this->driver, $this->drivers, true)) {
124throw EncryptionException::forUnKnownHandler($this->driver);
125}
126
127if (empty($this->key)) {
128throw EncryptionException::forNeedsStarterKey();
129}
130
131$this->hmacKey = bin2hex(\hash_hkdf($this->digest, $this->key));
132
133$handlerName = 'CodeIgniter\\Encryption\\Handlers\\' . $this->driver . 'Handler';
134$this->encrypter = new $handlerName($config);
135
136return $this->encrypter;
137}
138
139/**
140* Create a random key
141*
142* @param int $length Output length
143*
144* @return string
145*/
146public static function createKey($length = 32)
147{
148return random_bytes($length);
149}
150
151/**
152* __get() magic, providing readonly access to some of our protected properties
153*
154* @param string $key Property name
155*
156* @return array|string|null
157*/
158public function __get($key)
159{
160if ($this->__isset($key)) {
161return $this->{$key};
162}
163
164return null;
165}
166
167/**
168* __isset() magic, providing checking for some of our protected properties
169*
170* @param string $key Property name
171*/
172public function __isset($key): bool
173{
174return in_array($key, ['key', 'digest', 'driver', 'drivers'], true);
175}
176}
177