@@ -22,41 +22,25 @@ class HmacEncrypter
2222{
2323 /**
2424 * Codeigniter Encrypter
25+ *
26+ * @var array<string, EncrypterInterface>
2527 */
26- private EncrypterInterface $ encrypter ;
28+ private array $ encrypter ;
2729
2830 /**
2931 * Auth Token config
3032 */
3133 private AuthToken $ authConfig ;
3234
33- /**
34- * Selected Key Index
35- */
36- private string $ keyIndex ;
37-
3835 /**
3936 * Constructor
4037 * Setup encryption configuration
41- *
42- * @param bool $deprecatedKey Use the deprecated key (useful when re-encrypting on key rotation) [default: false]
4338 */
44- public function __construct (bool $ deprecatedKey = false )
39+ public function __construct ()
4540 {
46- /** @var AuthToken $authConfig */
47- $ authConfig = config ('AuthToken ' );
48- $ config = new Encryption ();
49-
50- // identify which encryption key should be used
51- $ this ->keyIndex = $ deprecatedKey ? $ authConfig ->hmacEncryption ['deprecatedKey ' ] : $ authConfig ->hmacEncryption ['currentKey ' ];
41+ $ this ->authConfig = config ('AuthToken ' );
5242
53- $ config ->key = $ authConfig ->hmacEncryption ['key ' ][$ this ->keyIndex ];
54- $ config ->driver = $ authConfig ->hmacEncryption ['driver ' ][$ this ->keyIndex ];
55- $ config ->digest = $ authConfig ->hmacEncryption ['digest ' ][$ this ->keyIndex ];
56-
57- $ this ->authConfig = $ authConfig ;
58- // decrypt secret key so signature can be validated
59- $ this ->encrypter = Services::encrypter ($ config );
43+ $ this ->getEncrypter ($ this ->authConfig ->hmacEncryption ['currentKey ' ]);
6044 }
6145
6246 /**
@@ -70,10 +54,15 @@ public function __construct(bool $deprecatedKey = false)
7054 */
7155 public function decrypt (string $ encString ): string
7256 {
73- // Removes `$b6$keyIndex$` for base64 format.
74- $ encString = substr ($ encString , strlen ($ this ->keyIndex ) + 5 );
57+ $ matches = [];
58+ // check for a match
59+ if (preg_match ('/^\$b6\$(\w+?)\$(.+)$/ ' , $ encString , $ matches ) !== 1 ) {
60+ throw new EncryptionException ('Unable to decrypt string ' );
61+ }
62+
63+ $ encrypter = $ this ->getEncrypter ($ matches [1 ]);
7564
76- return $ this -> encrypter ->decrypt (base64_decode ($ encString , true ));
65+ return $ encrypter ->decrypt (base64_decode ($ matches [ 2 ] , true ));
7766 }
7867
7968 /**
@@ -88,7 +77,9 @@ public function decrypt(string $encString): string
8877 */
8978 public function encrypt (string $ rawString ): string
9079 {
91- $ encryptedString = '$b6$ ' . $ this ->keyIndex . '$ ' . base64_encode ($ this ->encrypter ->encrypt ($ rawString ));
80+ $ currentKey = $ this ->authConfig ->hmacEncryption ['currentKey ' ];
81+
82+ $ encryptedString = '$b6$ ' . $ currentKey . '$ ' . base64_encode ($ this ->encrypter [$ currentKey ]->encrypt ($ rawString ));
9283
9384 if (strlen ($ encryptedString ) > $ this ->authConfig ->secret2StorageLimit ) {
9485 throw new RuntimeException ('Encrypted key too long. Unable to store value. ' );
@@ -102,15 +93,17 @@ public function encrypt(string $rawString): string
10293 */
10394 public function isEncrypted (string $ string ): bool
10495 {
105- return ( bool ) preg_match ('/^\$b6\$/ ' , $ string );
96+ return preg_match ('/^\$b6\$/ ' , $ string ) === 1 ;
10697 }
10798
10899 /**
109- * Check if the string already encrypted
100+ * Check if the string already encrypted with the Current Set Key
110101 */
111- public function isEncryptedWithSetKey (string $ string ): bool
102+ public function isEncryptedWithCurrentKey (string $ string ): bool
112103 {
113- return preg_match ('/^\$b6\$ ' . $ this ->keyIndex . '\$/ ' , $ string ) === 1 ;
104+ $ currentKey = $ this ->authConfig ->hmacEncryption ['currentKey ' ];
105+
106+ return preg_match ('/^\$b6\$ ' . $ currentKey . '\$/ ' , $ string ) === 1 ;
114107 }
115108
116109 /**
@@ -124,4 +117,28 @@ public function generateSecretKey(): string
124117 {
125118 return base64_encode (random_bytes ($ this ->authConfig ->hmacSecretKeyByteSize ));
126119 }
120+
121+ /**
122+ * Retrieve encrypter for selected key
123+ *
124+ * @param string $encrypterKey Index Key for selected Encrypter
125+ */
126+ private function getEncrypter (string $ encrypterKey ): EncrypterInterface
127+ {
128+ if (! isset ($ this ->encrypter [$ encrypterKey ])) {
129+ if (! isset ($ this ->authConfig ->hmacEncryption ['key ' ][$ encrypterKey ])) {
130+ throw new RuntimeException ('Encryption key does not exist. ' );
131+ }
132+
133+ $ config = new Encryption ();
134+
135+ $ config ->key = $ this ->authConfig ->hmacEncryption ['key ' ][$ encrypterKey ];
136+ $ config ->driver = $ this ->authConfig ->hmacEncryption ['driver ' ][$ encrypterKey ];
137+ $ config ->digest = $ this ->authConfig ->hmacEncryption ['digest ' ][$ encrypterKey ];
138+
139+ $ this ->encrypter [$ encrypterKey ] = Services::encrypter ($ config );
140+ }
141+
142+ return $ this ->encrypter [$ encrypterKey ];
143+ }
127144}
0 commit comments