Di seguito è la mia implementazione di crittografia in PHP. È basato su mcrypt e utilizza AES-128 in modalità CTR insieme a un HMAC RIPEMD-128 per il controllo dell'integrità.
Per brevità, ho sottolineato le funzioni per il calcolo dell'HMAC, verificando le HMAC, direttamente le funzioni int encrypt / decrypt. D'altra parte, ho aggiunto più commenti sotto rispetto al codice originale, per garantire che ciò che accade possa essere compreso correttamente da persone che non hanno familiarità con PHP 1 .
function encrypt($data, $key, $hmac_key) {
// Get the appropriate IV size for AES-128/CTR
$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, 'ctr');
// Create a random IV.
$iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
// Encrypt with AES-128/CTR with the provided key.
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, 'ctr', $iv);
// Base HMAC on the contatenated IV, the encrypted data and the cipher identifier.
$hmac_data = $iv . $encrypted . MCRYPT_RIJNDAEL_128;
// Calculate HMAC using ripemd128 and the supplied HMAC key.
$hmac = hash_hmac('ripemd128', $hmac_data, $hmac_key);
// Concatenate together the IV, encrypted data, and hmac, and base 64 encode them.
return base64_encode($iv . $encrypted . $hmac);
}
function decrypt($encrypted, $key, $hmac_key) {
// Decode from base 64.
$encrypted = base64_decode($encrypted);
// Get the appropriate IV size for AES-128/CTR
$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, 'ctr');
// Grab the IV and HMAC from the data.
$iv = substr($encrypted, 0, $ivSize);
$hmac = substr($encrypted, -32);
// Cut out the remaining data, which is the cipher text.
$encrypted = substr($encrypted, $ivSize, -32);
// Base HMAC on the contatenated IV, the encrypted data and the cipher identifier.
$hmac_data = $iv . $encrypted . MCRYPT_RIJNDAEL_128;
// Calculate verification HMAC using ripemd128 and the supplied HMAC key.
$verification_hmac = hash_hmac('ripemd128', $hmac_data, $hmac_key);
$verification = true;
// Refuse to proceed if the two HMACs are of different length.
if (strlen($hmac) !== strlen($verification_hmac)) {
return NULL;
}
// Always iterate over the entire length of the HMACs to avoid timing information.
for($i = 0; $i < strlen($verification_hmac); $i++) {
// Check for strict equality for each character.
if($verification_hmac[$i] !== $verification_hmac[$i]) {
$verification = false;
}
}
// Refuse to proceed if the two HMACs don't match exactly.
if (!$verification) {
return NULL;
}
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, 'ctr', $iv);
return $decrypted;
}
1 : penso principalmente all'operatore di concatenazione, punto (.), che potrebbe non essere del tutto ovvio.