• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 20643293754

01 Jan 2026 06:18PM UTC coverage: 85.468% (-0.03%) from 85.499%
20643293754

Pull #9863

github

web-flow
Merge 0d306a76b into ff20d8106
Pull Request #9863: feat: encryption key rotation support

86 of 94 new or added lines in 4 files covered. (91.49%)

9 existing lines in 1 file now uncovered.

21838 of 25551 relevant lines covered (85.47%)

203.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/system/Encryption/Handlers/OpenSSLHandler.php
1
<?php
2

3
declare(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

14
namespace CodeIgniter\Encryption\Handlers;
15

16
use CodeIgniter\Encryption\Exceptions\EncryptionException;
17
use SensitiveParameter;
18

19
/**
20
 * Encryption handling for OpenSSL library
21
 *
22
 * @see \CodeIgniter\Encryption\Handlers\OpenSSLHandlerTest
23
 */
24
class OpenSSLHandler extends BaseHandler
25
{
26
    /**
27
     * HMAC digest to use
28
     *
29
     * @var string
30
     */
31
    protected $digest = 'SHA512';
32

33
    /**
34
     * List of supported HMAC algorithms
35
     *
36
     * @var array [name => digest size]
37
     */
38
    protected array $digestSize = [
39
        'SHA224' => 28,
40
        'SHA256' => 32,
41
        'SHA384' => 48,
42
        'SHA512' => 64,
43
    ];
44

45
    /**
46
     * Cipher to use
47
     *
48
     * @var string
49
     */
50
    protected $cipher = 'AES-256-CTR';
51

52
    /**
53
     * Starter key
54
     *
55
     * @var string
56
     */
57
    protected $key = '';
58

59
    /**
60
     * Whether the cipher-text should be raw. If set to false, then it will be base64 encoded.
61
     */
62
    protected bool $rawData = true;
63

64
    /**
65
     * Encryption key info.
66
     * This setting is only used by OpenSSLHandler.
67
     *
68
     * Set to 'encryption' for CI3 Encryption compatibility.
69
     */
70
    public string $encryptKeyInfo = '';
71

72
    /**
73
     * Authentication key info.
74
     * This setting is only used by OpenSSLHandler.
75
     *
76
     * Set to 'authentication' for CI3 Encryption compatibility.
77
     */
78
    public string $authKeyInfo = '';
79

80
    /**
81
     * {@inheritDoc}
82
     */
83
    public function encrypt(#[SensitiveParameter] $data, #[SensitiveParameter] $params = null)
84
    {
85
        $key = $params !== null
11✔
86
            ? (is_array($params) && isset($params['key']) ? $params['key'] : $params)
9✔
87
            : $this->key;
2✔
88

89
        if (empty($key)) {
11✔
90
            throw EncryptionException::forNeedsStarterKey();
1✔
91
        }
92

93
        // derive a secret key
94
        $encryptKey = \hash_hkdf($this->digest, $key, 0, $this->encryptKeyInfo);
10✔
95

96
        // basic encryption
97
        $iv = ($ivSize = \openssl_cipher_iv_length($this->cipher)) ? \openssl_random_pseudo_bytes($ivSize) : null;
10✔
98

99
        $data = \openssl_encrypt($data, $this->cipher, $encryptKey, OPENSSL_RAW_DATA, $iv);
10✔
100

101
        if ($data === false) {
10✔
102
            throw EncryptionException::forEncryptionFailed();
×
103
        }
104

105
        $result = $this->rawData ? $iv . $data : base64_encode($iv . $data);
10✔
106

107
        // derive a secret key
108
        $authKey = \hash_hkdf($this->digest, $key, 0, $this->authKeyInfo);
10✔
109

110
        $hmacKey = \hash_hmac($this->digest, $result, $authKey, $this->rawData);
10✔
111

112
        return $hmacKey . $result;
10✔
113
    }
114

115
    /**
116
     * {@inheritDoc}
117
     */
118
    public function decrypt($data, #[SensitiveParameter] $params = null)
119
    {
120
        return $this->tryDecryptWithFallback($data, $params, function ($data, $params): string {
13✔
121
            $key = $params !== null
13✔
122
                ? (is_array($params) && isset($params['key']) ? $params['key'] : $params)
8✔
123
                : $this->key;
7✔
124

125
            if (empty($key)) {
13✔
NEW
126
                throw EncryptionException::forNeedsStarterKey();
×
127
            }
128

129
            // derive a secret key
130
            $authKey = \hash_hkdf($this->digest, $key, 0, $this->authKeyInfo);
13✔
131

132
            $hmacLength = $this->rawData
13✔
133
                ? $this->digestSize[$this->digest]
11✔
134
                : $this->digestSize[$this->digest] * 2;
2✔
135

136
            $hmacKey  = self::substr($data, 0, $hmacLength);
13✔
137
            $data     = self::substr($data, $hmacLength);
13✔
138
            $hmacCalc = \hash_hmac($this->digest, $data, $authKey, $this->rawData);
13✔
139

140
            if (! hash_equals($hmacKey, $hmacCalc)) {
13✔
141
                throw EncryptionException::forAuthenticationFailed();
6✔
142
            }
143

144
            $data = $this->rawData ? $data : base64_decode($data, true);
9✔
145

146
            if ($ivSize = \openssl_cipher_iv_length($this->cipher)) {
9✔
147
                $iv   = self::substr($data, 0, $ivSize);
9✔
148
                $data = self::substr($data, $ivSize);
9✔
149
            } else {
NEW
150
                $iv = null;
×
151
            }
152

153
            // derive a secret key
154
            $encryptKey = \hash_hkdf($this->digest, $key, 0, $this->encryptKeyInfo);
9✔
155

156
            $result = \openssl_decrypt($data, $this->cipher, $encryptKey, OPENSSL_RAW_DATA, $iv);
9✔
157

158
            if ($result === false) {
9✔
NEW
159
                throw EncryptionException::forAuthenticationFailed();
×
160
            }
161

162
            return $result;
9✔
163
        });
13✔
164
    }
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc