encrypt decrypt javascript php encryption cryptojs

decrypt - Encriptar con PHP, descifrar con Javascript(cryptojs)



cryptojs php (3)

Aviso de seguridad de Scott Arciszewski: el código de esta respuesta es vulnerable a los ataques de texto cifrado elegidos. Vea esta respuesta en su lugar para un cifrado seguro .

Aquí hay un ejemplo práctico de cifrar su cadena con PHP y descifrarla con CryptoJS.

En el lado de PHP:

Use MCRYPT_RIJNDAEL_128 (no 256) para emparejar con AES. El 128 aquí es el tamaño del bloque, no el tamaño de la clave.

Envía el IV , también. Necesitas el IV para descifrar.

$text = "this is the text here"; $key = "encryptionkey"; // Note: MCRYPT_RIJNDAEL_128 is compatible with AES (all key sizes) $iv = random_bytes(16); $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv); echo "iv:".base64_encode($iv)."/n"; echo "ciphertext:".base64_encode($ciphertext)."/n";

Aquí hay un resultado de muestra de una ejecución de prueba:

iv:BMcOODpuQurUYGICmOqqbQ== ciphertext:ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4=

Scott Arciszewski IMPORTANTE : Debido a que no estamos autenticando nuestro texto cifrado, el descifrado se vuelve vulnerable a los ataques oráculo de relleno . Ver también: encriptación autenticada en PHP .

En el lado de CryptoJS:

Su clave es de solo 13 caracteres imprimibles ASCII, que es muy débil. Mcrypt rellenó la clave de un tamaño de clave válido usando CERO bytes.

Convierta la clave y IV en arreglos de palabras .

No tuve mucha suerte descifrando con texto cifrado como un conjunto de palabras, así que lo dejé en formato Base64 .

CryptoJS = require("crypto-js") // Mcrypt pads a short key with zero bytes key = CryptoJS.enc.Utf8.parse(''encryptionkey/u0000/u0000/u0000'') iv = CryptoJS.enc.Base64.parse(''BMcOODpuQurUYGICmOqqbQ=='') // Keep the ciphertext in Base64 form ciphertext = ''ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4='' /** * Scott Arciszewski DANGER DANGER WILL ROBINSON! * * This example code doesn''t demonstrate AUTHENTICATED ENCRYPTION * and is therefore vulnerable to chosen-ciphertext attacks. * * NEVER USE THIS CODE TO PROTECT SENSITIVE DATA! */ // Mcrypt uses ZERO padding plaintext = CryptoJS.AES.decrypt(ciphertext, key, { iv: iv, padding: CryptoJS.pad.ZeroPadding }) // I ran this in nodejs process.stdout.write(CryptoJS.enc.Utf8.stringify(plaintext))

Estoy teniendo problemas con el cifrado / descifrado básico. He buscado un ejemplo que funcione pero no he encontrado un ejemplo que funcione.

-Estaré encriptando en php, descifrando con cryptojs para una pequeña capa de seguridad

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"> <? $text = "this is the text here"; $key = "encryptionkey"; $msgEncrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)); $msgBase64 = trim(base64_encode($msgEncrypted)); echo "<h2>PHP</h2>"; echo "<p>Encrypted:</p>"; echo $msgEncrypted; echo "<p>Base64:</p>"; echo $msgBase64; ?> <p>AES Decrypt</p> <script> var key = ''encryptionkey''; var encrypted = "<?php echo $msgBase64 ?>"; //tried var base64decode = CryptoJS.enc.Base64.parse(encrypted); var decrypted = CryptoJS.AES.decrypt(encrypted, key); console.log( decrypted.toString(CryptoJS.enc.Utf8) ); </script>

¿Qué paso me estoy perdiendo?


Está utilizando dos bibliotecas que intentan acomodar datos que, estrictamente hablando, no son válidos. Rijndael requiere claves con cadenas de bytes aleatorias de 16, 24 o 32 bytes de longitud. Usted proporciona una cadena de 13 caracteres. Mcrypt, la biblioteca de PHP, utiliza la cadena (presumible utf8 codificada) directamente como entrada binaria y cero lo MCRYPT_RIJNDAEL_256 a los 32 bytes necesarios para MCRYPT_RIJNDAEL_256 . Por otro lado, CryptoJS decide que ha ingresado algo así como una frase de contraseña y en su lugar utiliza una función de derivación de tecla para generar una clave de 32 bytes .

Además, los algoritmos de encriptación utilizados ni siquiera coinciden. Mcrypt usa una variante rara vez implementada del Rijndael original para la versión de 256 bits, mientras que CryptoJS implementa la ampliamente conocida variante AES256 de la propuesta Rijndael. La versión de 128 bits de ambos ( MCRYPT_RIJNDAEL_128 y AES128) son idénticos.

El tercer problema al que se enfrentará más adelante es que Mcrypt también utiliza un esquema de relleno loco para los datos que se cifran. Como Rijndael es un cifrado de bloques, solo puede encriptar bloques de 16, 24 o 32 bytes (dependiendo de la variante, AES siempre usa bloques de 16 bytes). Como tal, los datos deben ser rellenos. Mcrypt lo hace de una manera no inyectiva con solo agregar ceros. Si solo está codificando cadenas, esto no representará un problema para usted, ya que las cadenas codificadas con utf8 nunca contienen cero bytes, por lo que puede quitarlas ( CryptoJS incluso las admite de forma nativa ).

La solución más fácil a todos estos problemas es evitar tener que implementar cualquier criptografía (de todas maneras, se desaconseja encarecidamente sin un amplio conocimiento del tema). ¿Puedes transmitir tu información sensible a través de https que usará TLS (anteriormente llamado SSL) para encriptar y autenticar el canal?


He pedido lo mismo y escribí una pequeña biblioteca que funciona para CryptoJS 3.xy PHP con soporte para openssl. Espero que esto ayude, fuente más archivos de ejemplo aquí https://github.com/brainfoolong/cryptojs-aes-php

PHP Lib

/** * Decrypt data from a CryptoJS json encoding string * * @param mixed $passphrase * @param mixed $jsonString * @return mixed */ function cryptoJsAesDecrypt($passphrase, $jsonString){ $jsondata = json_decode($jsonString, true); $salt = hex2bin($jsondata["s"]); $ct = base64_decode($jsondata["ct"]); $iv = hex2bin($jsondata["iv"]); $concatedPassphrase = $passphrase.$salt; $md5 = array(); $md5[0] = md5($concatedPassphrase, true); $result = $md5[0]; for ($i = 1; $i < 3; $i++) { $md5[$i] = md5($md5[$i - 1].$concatedPassphrase, true); $result .= $md5[$i]; } $key = substr($result, 0, 32); $data = openssl_decrypt($ct, ''aes-256-cbc'', $key, true, $iv); return json_decode($data, true); } /** * Encrypt value to a cryptojs compatiable json encoding string * * @param mixed $passphrase * @param mixed $value * @return string */ function cryptoJsAesEncrypt($passphrase, $value){ $salt = openssl_random_pseudo_bytes(8); $salted = ''''; $dx = ''''; while (strlen($salted) < 48) { $dx = md5($dx.$passphrase.$salt, true); $salted .= $dx; } $key = substr($salted, 0, 32); $iv = substr($salted, 32,16); $encrypted_data = openssl_encrypt(json_encode($value), ''aes-256-cbc'', $key, true, $iv); $data = array("ct" => base64_encode($encrypted_data), "iv" => bin2hex($iv), "s" => bin2hex($salt)); return json_encode($data); }

Javascript Lib

var CryptoJSAesJson = { stringify: function (cipherParams) { var j = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)}; if (cipherParams.iv) j.iv = cipherParams.iv.toString(); if (cipherParams.salt) j.s = cipherParams.salt.toString(); return JSON.stringify(j); }, parse: function (jsonStr) { var j = JSON.parse(jsonStr); var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)}); if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv) if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s) return cipherParams; } }

Ejemplo de Javascript

var encrypted = CryptoJS.AES.encrypt(JSON.stringify("value to encrypt"), "my passphrase", {format: CryptoJSAesJson}).toString(); var decrypted = JSON.parse(CryptoJS.AES.decrypt(encrypted, "my passphrase", {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));

Ejemplo PHP

$encrypted = cryptoJsAesEncrypt("my passphrase", "value to encrypt"); $decrypted = cryptoJsAesDecrypt("my passphrase", $encrypted);