Cómo descifrar una cadena encriptada usando openssl_decrypt

Sep 18 2020

Estoy tratando de desarrollar un programa php que encripte algunos datos que luego puedan ser desencriptados. Sin embargo, tengo problemas para descifrar los datos con PHP usando el algoritmo AES-256-CBC usando el método openssl_decrypt () en PHP. El cifrado funciona, pero cuando trato de descifrar me da un error: -
hash_equals (): Se esperaba que known_string fuera una cadena, bool dado en la línea 44.

Mi código a continuación:

<?php

class Encryption{
    
    protected $data, $encryption_type, $key, $iv;

    public function __construct(){
        $mydata = "Is this safe"; $encryption = $this->secured_encryption($mydata);

        // Decrypting data
        $data_to_decrypt = $encryption;
        $this->decrypt_data($data_to_decrypt);
    }

    public function secured_encryption($data){ $this->data = $data; $this->encryption_type = "AES-256-CBC"; // cipher algorithm
        $this->key = ['6d2d823df2e08c0d3cdf70f148998d49', 'fdb3a18c7b0a322fdb3a18c7b0a320d3']; $this->iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->encryption_type)); $encrypted_data = openssl_encrypt($this->data, $this->encryption_type, $this->key[0], OPENSSL_RAW_DATA, $this->iv);
        $final_encryption = hash_hmac('SHA3-512', $encrypted_data, $this->key[1], true); $output = base64_encode($this->iv.$final_encryption.$encrypted_data); if($output):
            print("Encrypted data: {$output}<br/>"); else: print("Error in encrypting data"); endif; } public function decrypt_data($data){
        $this->data = base64_decode($data);
        $this->encryption_type = "AES-256-CBC"; // cipher algorithm $this->key = ['6d2d823df2e08c0d3cdf70f148998d49', 'fdb3a18c7b0a322fdb3a18c7b0a320d3'];
        $ivlen = openssl_cipher_iv_length($this->encryption_type);
        $this->iv = substr($this->data, 0, $ivlen); $hmac = substr($this->data, $ivlen, $sha2len = 32); $decrypt_data = substr($this->data, $ivlen, $sha2len); $final_decryption = openssl_decrypt($decrypt_data, $this->encryption_type, $this->key[0], OPENSSL_RAW_DATA, $this->iv);
        $calcmac = hash_hmac('SHA3-512', $decrypt_data, $this->key[1], true); if(hash_equals($hmac, $calcmac)): print($final_decryption);
        else:
            print("Error in decrypting data");
        endif;
    }
}

$encryption = Encryption();

?> 

Alguien que me ayude

Respuestas

3 Topaco Sep 18 2020 at 15:19

Hay algunos problemas menores en el código:

  • Falta una declaración de devolución en el secured_encryptionmétodo. Este es el desencadenante del mensaje de error ( hash_equals (): Se espera que la cadena conocida sea una cadena, dado el valor bool ), ya $hmacque no contiene una cadena, pero sí false. Entonces, al final, secured_encryptiondebes agregar:

    return $output;
    

    Con esto, el cifrado funciona, pero el descifrado aún no funciona.

  • Cuando se utiliza la separación del HMac en decrypt_datala longitud incorrecta. SHA3-512 da como resultado un hash de 512 bits, es decir, 64 bytes, es decir:

    $hmac = substr($this->data, $ivlen, $sha2len = 32);
    

    debe ser reemplazado por:

    $hmac = substr($this->data, $ivlen, $sha2len = 64);   
    
  • Al separar los datos, comience en la posición $ivlen + $sha2leny considere todo hasta el final, es decir:

    $decrypt_data = substr($this->data, $ivlen, $sha2len); 
    

    debe ser reemplazado por:

    $decrypt_data = substr($this->data, $ivlen + $sha2len);
    

Con estos cambios todo funciona y una salida se ve, por ejemplo, así:

Encrypted data: uTjcPmLK8jTktJ0oy5AqB40d5YFuAbgXMHfNEM6+JOH+DtyYAhckcv3mkLhdOvUqPlriKqYjHO6cpJI3ZdoTSS4lqDr0eH0MMiUpJMSXcan81irvobcdIV+rvaMPPRj7
Is this safe 

Por cierto, además del texto cifrado, también se debe autenticar el IV, ver aquí . También hay modos de operación autenticables que brindan tanto confidencialidad como autenticación, p. Ej. GCM (p aes-256-gcm. Ej. ), S. Comentario de Peter. Puede comprobar openssl_get_cipher_methods()qué algoritmos / modos están disponibles en su entorno.