La mia crittografia AES / CTR / RIPEMD è stata implementata correttamente?

3

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.

    
posta user50849 08.03.2014 - 23:06
fonte

1 risposta

2

Mi sembra a posto, tranne il tuo uso di RIPEMD128, su cui Wikipedia ha questo da dire:

The 128-bit version was intended only as a drop-in replacement for the original RIPEMD, which was also 128-bit, and which had been found to have questionable security.

Ti suggerisco di scegliere un hash migliore per la tua autenticità, ad es. SHA256 o almeno RIPEMD160.

    
risposta data 08.03.2014 - 23:45
fonte

Leggi altre domande sui tag