Cifrar con PHP, Descifrar con Javascript (cryptojs)

Estoy teniendo problemas con la básica de cifrado/descifrado. He mirado todo un ejemplo de trabajo, pero no he encontrado un ejemplo de trabajo.

-Voy a estar cifrado en php, descifrado, con cryptojs por 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>

Que paso me estoy perdiendo?

InformationsquelleAutor user2769 | 2014-06-21

4 Kommentare

  1. 52

    He requiere la misma cosa y me escribió una breve biblioteca que funciona para CryptoJS 3.x y PHP con soporte para openssl. Espero que esto ayude, la 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 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);
    • Agrega las partes principales de el código
    • Se ve bastante buena. Pero, ¿por qué usted decide no usar el IV/Sal?
    • Por CIERTO, sólo quiero añadir, es increíble que acaba de publicar esto… exactamente lo que estaba buscando, ya Mcrypt es GPL, donde OpenSSL es Apache/BSD
    • Quería seguir el ejemplo tan corto como sea posible – sino Que debe mostrar cómo el flujo básico de las obras. Yo soy también un cripto experto y no estoy seguro de lo que una costumbre IV y personalizado de sal debe ayudar. Sal y IV existen y siempre es diferente porque la sal se genera de forma aleatoria y IV resultados de la frase de acceso aleatorio y la sal. Pero cuando usted puede mejorar ese código por favor, hacerlo en mi repositorios GIT.
    • Es allí cualquier licencias en el código anterior? Sólo quieren asegurarse de que en caso de que quiero distribuir el código con mis otras cosas.
    • La GPL v3 – voy a agregar los repositorios de GitHub léame.
    • Saludos compañero.
    • puede alguna forma de obtener estática cadena cifrada en lugar de al azar cadena cifrada mediante el uso de este método..?
    • buen trabajo!
    • Después de tratar de obtener mi propio código para trabajar de todo el día, encontrando que la que había pasado el tiempo de escribir esto realmente ayudó. Y luego lo que realmente funcionó y ahora estoy sin palabras XD
    • Hii, el código php de Arriba no está funcionando para cifrar y descifrar a partir de los datos recibidos a través de cryptojs
    • Puede usted por favor me ayude, ¿cómo puedo utilizar este código

  2. 14

    Aviso de seguridad: El código de esta respuesta es vulnerable a los elegidos-los ataques de texto cifrado. Ver esta respuesta en lugar de cifrado seguro.

    Aquí es un ejemplo de trabajo de la encriptación de su cadena con PHP y descifrarla con CryptoJS.

    En el PHP lado:

    Uso MCRYPT_RIJNDAEL_128 (no 256) a la par con AES. El 128 aquí es el tamaño de los bloques, no el tamaño de la clave.

    Enviar el IV, demasiado. Usted necesita el IV a 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í es muestra de la salida de la ejecución de una prueba:

    iv:BMcOODpuQurUYGICmOqqbQ==
    ciphertext:ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4=

    IMPORTANTE: Porque no estamos de autenticación nuestro texto cifrado, el descifrado se vuelve vulnerable a padding oracle ataques. Ver también: autenticada de la codificación en PHP.

    Sobre la CryptoJS lado:

    Su clave es sólo 13 ASCII de los caracteres imprimibles que es muy débil. Mcrypt collar de la clave para una válida keysize utilizando CERO bytes.

    Convertir el clave y IV a palabra matrices.

    Yo no tuve mucha suerte descifrar con texto cifrado como una palabra de la matriz, así que lo he dejado en Base64 formato.

    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='
    
    /**
     * DANGER DANGER WILL ROBINSON! <== Stop editing my answer or I will delete it.
     *
     * 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))
    • Gracias! Yo no era capaz de conseguir que su ejemplo de trabajo, lamentablemente. Cuando me he quitado el «padding: CryptoJS.almohadilla.ZeroPadding», sería sortof trabajo –, pero añade que «���» al final de la cadena. También, me preguntaba cómo cambiar el encrpytion clave en su ejemplo. ¿Qué significa «\u0000\u0000\u0000» significa y cómo puedo determinar cuánto necesito?
    • «este es el texto aquí» codificado en UTF-16 42 bytes, que sería collar de 48 para el cifrado. Los 6 bytes aparecería como tres UTF-16 caracteres al final, lo que explicaría tres divertidos caracteres. Trate De CryptoJS.almohadilla.NoPadding, y mirar el valor binario de los últimos bytes. Son todos ellos 0x00, o todos 0x06?
    • Cada \u0000 es la adición de un cero byte 0x00, o dos bytes cero si la cadena es UTF-16. Mcrypt debe ser el relleno de la clave de 16, 24 o 32 bytes. Si este es el ASCII o UTF-8, que debería ser de 16 bytes. Si UTF-16, luego de 32 bytes. Usted debe usar una mejor clave. Elija un tamaño de clave de 16, 24 o 32 bytes y lo hacemos a partir de datos aleatorios criptográficamente fuerte.
    • MCRYPT_RAND no es un CSPRNG. Quieres un CSPRNG para IVs en el modo CBC. También, tonyarcieri.com/…
    • funciona como un encanto.. gracias SEÑOR
    • Las actualizaciones a su respuesta son visibles a partir de las revisiones de enlace.
    • Dejar de editar mi respuesta por razones frívolas o voy a eliminarlo. Signo de su graffiti.

  3. 3

    Se están utilizando dos bibliotecas que tratar de dar cabida a la entrada que es – en sentido estricto – no es válido. Rijndael requiere claves de 16, 24 o 32 bytes aleatorios cadenas de bytes. Usted proporciona un 13 cadena de caracteres. Mcrypt, la biblioteca de PHP, utiliza la cadena (presumible codificado en utf8) directamente como entrada binaria y zero pastillas para la necesaria 32 bytes para MCRYPT_RIJNDAEL_256. CryptoJS por otro lado decide que ha introducido algo así como una frase de paso y en su lugar utiliza una clave de derivación de la función para generar un 32 bytes de la clave.

    Además los algoritmos de cifrado utilizados incluso no coinciden. Mcrypt utiliza una rara vez se implementan variante de la original Rijndael de 256 bits, mientras que CryptoJS implementa el ampliamente conocido variante AES256 de la Rijndael propuesta. La 128 bits de la versión de ambos (MCRYPT_RIJNDAEL_128 y AES128) son idénticos, aunque.

    El tercer problema que se acerca a la cara posterior es que Mcrypt también utiliza un loco esquema de relleno de los datos cifrados. Como Rijndael, es un cifrado de bloque, sólo puede cifrar bloques de 16, 24 o 32 bytes (dependiendo de la variante – AES siempre utiliza bloques de 16 bytes). Como estos datos tiene que ser rellenado. Mcrypt hace en un no inyectiva manera simplemente añadiendo ceros. Si son sólo cadenas de codificación, esto no será un gran problema para usted como codificado en utf8 cadenas nunca contener cero bytes, por lo que sólo puede despojar a ellos (CryptoJS incluso admite que de forma nativa).

    La más fácil solución para todos estos problemas es para evitar tener que implementar cualquier criptografía de sí mismo (no se recomienda de todos modos sin un amplio conocimiento de la materia). Puede que en lugar de transmitir su información sensible a través de https que utilice TLS (anteriormente llamado SSL) para cifrar y autenticar el canal?

    • No te refieres a MCRYPT_RIJNDAEL_ 128 en el párrafo 2?
    • tienes razón, gracias.
  4. 0

    No vaya demasiado departamento con la codificación, sólo tiene que utilizar base64 decodificador

    en código php:

    $encrypt_val=base64_encode("value");

    y en js solo:

    var my_orignal_val = window.atob(passed_val);

    Ello será suficiente para su requisito.

    • en realidad, var my_orignal_val = window.btoa(passed_val);

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea