¿Mi encriptación AES / CTR / RIPEMD está correctamente implementado?

3

A continuación se muestra mi implementación de cifrado en PHP. Se basa en mcrypt y usa AES-128 en modo CTR junto con un RIPEMD-128 HMAC para la verificación de integridad.

Por brevedad, he incorporado las funciones para calcular HMAC, verificar HMAC, directamente en funciones de cifrado / descifrado. Por otro lado, he agregado más comentarios a continuación que el código original, para garantizar que las personas que no están familiarizadas con PHP 1 entiendan lo que sucede.

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 : Estoy pensando principalmente en el operador de concatenación, punto (.), que puede no ser del todo obvio.

    
pregunta user50849 08.03.2014 - 23:06
fuente

1 respuesta

2

Me parece bien, excepto por el uso de RIPEMD128, sobre lo que Wikipedia tiene esto que decir:

  

La versión de 128 bits fue pensada solo como un reemplazo directo del RIPEMD original, que también era de 128 bits, y se encontró que tenía una seguridad cuestionable.

Le sugiero que elija un hash mejor para su autenticidad, por ejemplo. SHA256 o al menos RIPEMD160.

    
respondido por el Polynomial 08.03.2014 - 23:45
fuente

Lea otras preguntas en las etiquetas