public function decrypt($data, array $params = NULL)
{
if (($params = $this->_get_params($params)) === FALSE) {
return FALSE;
}
if (isset($params['hmac_digest'])) {
// This might look illogical, but it is done during encryption as well ...
// The 'base64' value is effectively an inverted "raw data" parameter
$digest_size = $params['base64'] ? $this->_digests[$params['hmac_digest']] * 2 : $this->_digests[$params['hmac_digest']];
if (self::strlen($data) <= $digest_size) {
return FALSE;
}
$hmac_input = self::substr($data, 0, $digest_size);
$data = self::substr($data, $digest_size);
isset($params['hmac_key']) or $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
$hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], !$params['base64']);
// Time-attack-safe comparison
$diff = 0;
for ($i = 0; $i < $digest_size; $i++) {
$diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]);
}
if ($diff !== 0) {
return FALSE;
}
}
if ($params['base64']) {
$data = base64_decode($data);
}
isset($params['key']) or $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
return $this->{'_' . $this->_driver . '_decrypt'}($data, $params);
}