key = $params['key']; } else { $this->key = $params; } } if (empty($this->key)) { throw EncryptionException::forNeedsStarterKey(); } // derive a secret key $secret = \hash_hkdf($this->digest, $this->key); // basic encryption $iv = ($iv_size = \openssl_cipher_iv_length($this->cipher)) ? \openssl_random_pseudo_bytes($iv_size) : null; $data = \openssl_encrypt($data, $this->cipher, $secret, OPENSSL_RAW_DATA, $iv); if ($data === false) { throw EncryptionException::forEncryptionFailed(); } $result = $iv . $data; $hmacKey = \hash_hmac($this->digest, $result, $secret, true); $result = $hmacKey . $result; return $result; } // -------------------------------------------------------------------- /** * Decrypt ciphertext, with optional HMAC and base64 encoding * * @param string $data Encrypted data * @param array $params Over-ridden parameters, specifically the key * @return string * @throws \CodeIgniter\Encryption\EncryptionException */ public function decrypt($data, $params = null) { // Allow key over-ride if (! empty($params)) { if (isset($params['key'])) { $this->key = $params['key']; } else { $this->key = $params; } } if (empty($this->key)) { throw EncryptionException::forStarterKeyNeeded(); } // derive a secret key $secret = \hash_hkdf($this->digest, $this->key); $hmacLength = self::substr($this->digest, 3) / 8; $hmacKey = self::substr($data, 0, $hmacLength); $data = self::substr($data, $hmacLength); $hmacCalc = \hash_hmac($this->digest, $data, $secret, true); if (! hash_equals($hmacKey, $hmacCalc)) { throw EncryptionException::forAuthenticationFailed(); } if ($iv_size = \openssl_cipher_iv_length($this->cipher)) { $iv = self::substr($data, 0, $iv_size); $data = self::substr($data, $iv_size); } else { $iv = null; } return \openssl_decrypt($data, $this->cipher, $secret, OPENSSL_RAW_DATA, $iv); } }