Subversion Repositories oidplus

Compare Revisions

Regard whitespace Rev 1358 → Rev 1359

/trunk/includes/functions.inc.php
702,25 → 702,29
* @throws \Exception
*/
function encrypt_str(string $data, string $key): string {
if (function_exists('openssl_encrypt')) {
if (!function_exists('openssl_encrypt')) {
throw new OIDplusException(_L('Decryption failed (OpenSSL not installed)'));
}
 
$iv = random_bytes(16); // AES block size in CBC mode
 
// In 2023, OWASP recommended to use 600,000 iterations for PBKDF2-HMAC-SHA256 and 210,000 for PBKDF2-HMAC-SHA512.
$version = 'V2023A';
 
// Encryption
$ciphertext = openssl_encrypt(
$data,
'AES-256-CBC',
hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, true),
hash_pbkdf2('sha512', $key, '', 210000, 32/*256bit*/, true),
OPENSSL_RAW_DATA,
$iv
);
 
// Authentication
$hmac = sha3_512_hmac($iv . $ciphertext, $key, true);
return $hmac . $iv . $ciphertext;
} else {
// When OpenSSL is not available, then we just do a HMAC
$hmac = sha3_512_hmac($data, $key, true);
return $hmac . $data;
 
return $version . $hmac . $iv . $ciphertext;
}
}
 
/**
* @param string $data
729,35 → 733,36
* @throws OIDplusException
*/
function decrypt_str(string $data, string $key): string {
if (function_exists('openssl_decrypt')) {
$hmac = mb_substr($data, 0, 64, '8bit');
$iv = mb_substr($data, 64, 16, '8bit');
$ciphertext = mb_substr($data, 80, null, '8bit');
if (!function_exists('openssl_decrypt')) {
throw new OIDplusException(_L('Decryption failed (OpenSSL not installed)'));
}
 
$version = mb_substr($data, 0, 6, '8bit');
$hmac = mb_substr($data, 6, 64, '8bit');
$iv = mb_substr($data, 70, 16, '8bit');
$ciphertext = mb_substr($data, 86, null, '8bit');
 
if ($version === 'V2023A') {
// Authentication
$hmacNew = sha3_512_hmac($iv . $ciphertext, $key, true);
if (!hash_equals($hmac, $hmacNew)) {
throw new OIDplusException(_L('Authentication failed'));
throw new OIDplusException(_L('Decryption failed (wrong password)'));
}
 
// Decryption
$cleartext = openssl_decrypt(
$ciphertext,
'AES-256-CBC',
hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, true),
hash_pbkdf2('sha512', $key, '', 210000, 32/*256bit*/, true),
OPENSSL_RAW_DATA,
$iv
);
} else {
throw new OIDplusException(_L('Decryption failed (Unexpected encryption version)'));
}
 
if ($cleartext === false) {
throw new OIDplusException(_L('Decryption failed'));
throw new OIDplusException(_L('Decryption failed (Internal error)'));
}
return $cleartext;
} else {
// When OpenSSL is not available, then we just do a HMAC
$hmac = mb_substr($data, 0, 64, '8bit');
$cleartext = mb_substr($data, 64, null, '8bit');
$hmacNew = sha3_512_hmac($cleartext, $key, true);
if (!hash_equals($hmac, $hmacNew)) {
throw new OIDplusException(_L('Authentication failed'));
}
return $cleartext;
}
}