mcrypt_encrypt mcrypt_decrypt alternative php openssl mcrypt

php - mcrypt_decrypt - Reemplazar Mcrypt con OpenSSL



mcrypt_decrypt alternative (4)

@clover tiene razón en que el relleno predeterminado para Blowfish es diferente entre mcrypt y Openssl, pero es incorrecto que no se pueda hacer. Si usa la opción OPENSSL_ZERO_PADDING para descifrar, los dos son compatibles:

openssl_decrypt($data, ''bf-ecb'', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);

Actualmente tenemos una implementación de mcrypt en nuestros sistemas para cifrar algunos datos sensibles en nuestra aplicación PHP. Ahora tenemos un nuevo requisito de que tenemos que cambiar el módulo crypt a openssl. Otra cosa que es importante saber es que estamos usando el pez globo de cifrado y el modo ecb. Entonces comencé a probar cuáles son las diferencias y cómo puedo descifrar mcrypt cadenas encriptadas con openssl.

Usé la función estándar de PHP:

  • mcrypt_encrypt vs. openssl_encrypt
  • mcrypt_decrypt vs. openssl_decrypt

Ambos métodos están dando resultados diferentes. Lo segundo es que en el cifrado dado (pez globo) y el modo (ecb) en ambos tipos se requieren diferentes longitudes IV (openssl = 0 y mcrypt = 56).

¿Alguien sabe cómo puedo cambiar fácilmente los módulos sin tener un gran esfuerzo de migración?

¡Gracias por adelantado!

ACTUALIZAR:

Aquí está el código, que lo probé:

<?php function say($message){ if(!is_string($message)){ if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "<pre>"; echo var_export($message, true) . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "/n" : "<br />")); if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "</pre>"; }else{ echo $message . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "/n" : "<br />")); } } say("= Begin raw encryption"); $key = "anotherpass"; $str = "does it work"; say(" Params:"); say(" - String to encrypt ''".$str."''"); say(" - Key: ".$key); say(""); $params = array( "openssl" => array( "cipher" => "BF", "mode" => "ECB", ), "mcrypt" => array( "cipher" => "blowfish", "mode" => "ecb", ), ); say("= Mcrypt"); $handler = mcrypt_module_open($params[''mcrypt''][''cipher''], '''', $params[''mcrypt''][''mode''], ''''); $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($handler), MCRYPT_RAND); $keysize = mcrypt_enc_get_key_size($handler); mcrypt_generic_init($handler,$key,"/0/0/0/0/0/0/0/0"); say(" Params:"); say(" - InitVector ".bin2hex($iv)." (bin2hex)"); say(" - Max keysize ".$keysize); say(" - Cipher ".$params[''mcrypt''][''cipher'']); say(" - Mode ".$params[''mcrypt''][''mode'']); say(""); say(" Encryption:"); $m_encrypted = mcrypt_generic($handler, $str); $m_decrypted = mdecrypt_generic($handler, $m_encrypted); say(" - Encrypted ".bin2hex($m_encrypted)." (bin2hex)"); say(" - Descrypted ".$m_decrypted); say(""); say("= Openssl"); say(" Params:"); say(" - InitVector not needed"); say(" - Max keysize ".openssl_cipher_iv_length($params[''openssl''][''cipher'']."-".$params[''openssl''][''mode''])); say(" - Cipher ".$params[''openssl''][''cipher'']); say(" - Mode ".$params[''openssl''][''mode'']); say(""); say(" Encryption:"); $o_encrypted = openssl_encrypt($str,$params[''openssl''][''cipher'']."-".$params[''openssl''][''mode''],$key,true); $o_decrypted = openssl_decrypt($o_encrypted,$params[''openssl''][''cipher'']."-".$params[''openssl''][''mode''],$key,true); say(" - Encrypted ".bin2hex($o_encrypted)." (bin2hex)"); say(" - Descrypted ".$o_decrypted);

Y este es mi resultado:

= Begin raw encryption Params: - String to encrypt ''does it work'' - Key: anotherpass = Mcrypt Params: - InitVector 06a184909d7bf863 (bin2hex) - Max keysize 56 - Cipher blowfish - Mode ecb Encryption: - Encrypted 0e93dce9a6a88e343fe5f90d1307684c (bin2hex) - Descrypted does it work = Openssl Params: - InitVector not needed - Max keysize 0 - Cipher BF - Mode ECB Encryption: - Encrypted 213460aade8f9c14d8d51947b8231439 (bin2hex) - Descrypted does it work

Tal vez alguna idea ahora?

¡Gracias!


Blowfish es el cifrado de bloque. Requiere que los datos se rellenen antes del cifrado. OpenSSL usa PKCS # 7 y mcrypt usa PKCS # 5. Diferentes algoritmos de relleno para los datos. La longitud mínima de relleno PKCS # 5 es 0, para PKCS # 7 es 1 ( wikipedia ). Eche un vistazo a este ejemplo (he rellenado manualmente los datos de entrada para mcrypt_encrypt() en el estilo PKCS # 7):

<?php $key = "anotherpassword1"; $str = "does it work 12"; $enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $str."/1", MCRYPT_MODE_ECB); $dec = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $enc, MCRYPT_MODE_ECB); echo(bin2hex($enc).PHP_EOL); var_dump($dec); $enc = openssl_encrypt($str, ''bf-ecb'', $key, true); $dec = openssl_decrypt($enc, ''bf-ecb'', $key, true); echo(bin2hex($enc).PHP_EOL); var_dump($dec); ?>

Es imposible abrir los datos de openssl_decrypt () encriptados con mcrypt_encrypt (), a menos que se realice un relleno de datos manual con PKCS # 7 antes de mcrypt_encrypt() .

Solo hay una forma en su caso: volver a codificar los datos.

PD: hay un error en su fuente: el modo ECB no usa IV ( wikipedia )


En caso de que desee cifrar con openssl y aún obtener el mismo resultado que si lo hubiera cifrado con mcrypt al descifrarlo con mcrypt, necesita anular manualmente la cadena de entrada antes de OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING con openssl_encrypt y pasar la OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING opciones.

$str = ''encrypt me''; $cipher = ''AES-256-CBC''; $key = ''01234567890123456789012345678901''; $opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; $iv_len = 16; $str_len = mb_strlen($str, ''8bit''); $pad_len = $iv_len - ($str_len % $iv_len); $str .= str_repeat(chr(0), $pad_len); $iv = openssl_random_pseudo_bytes($iv_len); $encrypted = openssl_encrypt($str, $cipher, $key, $opts, $iv);

El descifrado con mcrypt_decrypt funcionará como si también hubiera utilizado mcrypt para el cifrado.

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv)