Skip to content

Commit 2f58622

Browse files
committed
refactor: add support for both string and array $previousKeys and made decrypt functions more readable.
1 parent 6a8694f commit 2f58622

File tree

5 files changed

+64
-47
lines changed

5 files changed

+64
-47
lines changed

app/Config/Encryption.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Encryption extends BaseConfig
3030
* If you want to enable decryption using previous keys, set them here.
3131
* See the user guide for more info.
3232
*/
33-
public string $previousKeys = '';
33+
public string|array $previousKeys = '';
3434

3535
/**
3636
* --------------------------------------------------------------------------

system/Config/BaseConfig.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,14 @@ public function __construct()
134134
if ($property === 'key') {
135135
$this->{$property} = $this->parseEncryptionKey($this->{$property});
136136
} elseif ($property === 'previousKeys') {
137-
$keysArray = array_map(trim(...), explode(',', $this->{$property}));
137+
$keysArray = is_string($this->{$property}) ? array_map(trim(...), explode(',', $this->{$property})) : $this->{$property};
138138
$parsedKeys = [];
139139

140140
foreach ($keysArray as $key) {
141141
$parsedKeys[] = $this->parseEncryptionKey($key);
142142
}
143-
$this->{$property} = implode(',', $parsedKeys);
143+
144+
$this->{$property} = $parsedKeys;
144145
}
145146
}
146147
}

system/Encryption/Encryption.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ class Encryption
5454
protected $key;
5555

5656
/**
57-
* Comma-separated list of previous keys for fallback decryption.
57+
* Array or Comma-separated list of previous keys for fallback decryption.
58+
*
59+
* @var string|array<string>
5860
*/
59-
protected string $previousKeys = '';
61+
protected string|array $previousKeys = '';
6062

6163
/**
6264
* The derived HMAC key

system/Encryption/Handlers/OpenSSLHandler.php

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class OpenSSLHandler extends BaseHandler
5959
/**
6060
* List of previous keys for fallback decryption.
6161
*/
62-
protected string $previousKeys = '';
62+
protected string|array $previousKeys = '';
6363

6464
/**
6565
* Whether the cipher-text should be raw. If set to false, then it will be base64 encoded.
@@ -132,32 +132,39 @@ public function decrypt($data, #[SensitiveParameter] $params = null)
132132
throw EncryptionException::forNeedsStarterKey();
133133
}
134134

135-
$result = false;
135+
// Only use fallback keys if no custom key was provided in params
136+
$useFallback = !isset($params['key']);
136137

137-
try {
138-
$result = $this->decryptWithKey($data, $this->key);
139-
} catch (EncryptionException $e) {
140-
$exception = $e;
138+
$attemptDecrypt = function ($key) use ($data) {
139+
try {
140+
$result = $this->decryptWithKey($data, $key);
141+
return ['success' => true, 'data' => $result];
142+
} catch (EncryptionException $e) {
143+
return ['success' => false, 'exception' => $e];
144+
}
145+
};
146+
147+
$result = $attemptDecrypt($this->key);
148+
149+
if ($result['success']) {
150+
return $result['data'];
141151
}
142152

143-
if ($result === false && $this->previousKeys !== '') {
144-
foreach (explode(',', $this->previousKeys) as $previousKey) {
145-
try {
146-
$result = $this->decryptWithKey($data, $previousKey);
147-
if ($result !== false) {
148-
return $result;
149-
}
150-
} catch (EncryptionException) {
151-
// Try next key
153+
$originalException = $result['exception'];
154+
155+
// If primary key failed and fallback is allowed, try previous keys
156+
if ($useFallback && !empty($this->previousKeys)) {
157+
foreach ($this->previousKeys as $previousKey) {
158+
$fallbackResult = $attemptDecrypt($previousKey);
159+
160+
if ($fallbackResult['success']) {
161+
return $fallbackResult['data'];
152162
}
153163
}
154164
}
155165

156-
if (isset($exception)) {
157-
throw $exception;
158-
}
159-
160-
return $result;
166+
// All attempts failed - throw the original exception
167+
throw $originalException;
161168
}
162169

163170
/**

system/Encryption/Handlers/SodiumHandler.php

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace CodeIgniter\Encryption\Handlers;
1515

1616
use CodeIgniter\Encryption\Exceptions\EncryptionException;
17+
use phpDocumentor\Reflection\PseudoTypes\NonEmptyString;
1718
use SensitiveParameter;
1819

1920
/**
@@ -34,7 +35,7 @@ class SodiumHandler extends BaseHandler
3435
/**
3536
* List of previous keys for fallback decryption.
3637
*/
37-
protected string $previousKeys = '';
38+
protected string|array $previousKeys = '';
3839

3940
/**
4041
* Block size for padding message.
@@ -85,34 +86,40 @@ public function decrypt($data, #[SensitiveParameter] $params = null)
8586
throw EncryptionException::forNeedsStarterKey();
8687
}
8788

88-
$result = false;
89+
// Only use fallback keys if no custom key was provided in params
90+
$useFallback = !isset($params['key']);
91+
92+
$attemptDecrypt = function ($key) use ($data) {
93+
try {
94+
$result = $this->decryptWithKey($data, $key);
95+
sodium_memzero($key);
96+
return ['success' => true, 'data' => $result];
97+
} catch (EncryptionException $e) {
98+
sodium_memzero($key);
99+
return ['success' => false, 'exception' => $e];
100+
}
101+
};
102+
103+
$result = $attemptDecrypt($this->key);
89104

90-
try {
91-
$result = $this->decryptWithKey($data, $this->key);
92-
sodium_memzero($this->key);
93-
} catch (EncryptionException $e) {
94-
$exception = $e;
95-
sodium_memzero($this->key);
105+
if ($result['success']) {
106+
return $result['data'];
96107
}
97108

98-
if ($result === false && $this->previousKeys !== '') {
99-
foreach (explode(',', $this->previousKeys) as $previousKey) {
100-
try {
101-
$result = $this->decryptWithKey($data, $previousKey);
102-
if (isset($result)) {
103-
return $result;
104-
}
105-
} catch (EncryptionException) {
106-
// Try next key
109+
$originalException = $result['exception'];
110+
111+
// If primary key failed and fallback is allowed, try previous keys
112+
if ($useFallback && !empty($this->previousKeys)) {
113+
foreach ($this->previousKeys as $previousKey) {
114+
$fallbackResult = $attemptDecrypt($previousKey);
115+
116+
if ($fallbackResult['success']) {
117+
return $fallbackResult['data'];
107118
}
108119
}
109120
}
110121

111-
if (isset($exception)) {
112-
throw $exception;
113-
}
114-
115-
return $result;
122+
throw $originalException;
116123
}
117124

118125
/**

0 commit comments

Comments
 (0)