Estoy cifrar mi contraseña de usuario en JavaScript como este:

 var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase");

Funciona bien, pero ahora estoy tratando de descifrar en PHP en el lado del servidor como este:

 $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
 $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($password), MCRYPT_MODE_CBC, $iv);

no funciona en todos, la contraseña descifrada cadena parece muy extraño:

 string(64) ">�OX2MS��댗v�<$�ʕ��i�̄��_��P���\�կ=�_6(�m����,4WT7��a"

Aquí es el estado actual de mi código en JavaScript después de los comentarios útiles:

    var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase");
    var ivHex = encryptedPassword.iv.toString();
    var ivSize = encryptedPassword.algorithm.ivSize; //same as blockSize
    var keySize = encryptedPassword.algorithm.keySize;
    var keyHex = encryptedPassword.key.toString();
    var saltHex = encryptedPassword.salt.toString(); //must be sent
    var openSslFormattedCipherTextString = encryptedPassword.toString(); //not used
    var cipherTextHex = encryptedPassword.ciphertext.toString(); //must be sent

Estoy enviando saltHex y CipherTextHex para el PHP del servidor y estoy usando mcrypt_decrypt() como este:

 $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), $saltHex);
 $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($cipherTextHex), MCRYPT_MODE_CBC, $iv);

Todavía no trabajar con este código actualizado.

Alguien me puede ayudar a descifrar correctamente con mcrypt_decrypt() de PHP, la función de un simple método de cifrado AES ? Estoy seguro de que estoy haciendo algo mal con el sistema de cifrado, mcrypt modo y en el IV parámetros dentro de mi mcrypt_decrypt() método. Gracias si saben.

la clave != contraseña
Puede usted por favor, dar más precisión ?
¿Cuál es la ventaja de cifrado en JavaScript y descifrar en PHP, Porque se puede hacer cifrar y descifrar en PHP
Ver aquí: stackoverflow.com/a/27250883/1816580 y convertir el código php si quieres
Si usted no tiene la IV y la sal, a continuación, usted está fuera de suerte. No mostrar cómo encryptedPassword se transmite, porque puede ser codificado ito. CryptoJS utiliza un OpenSSLFormatter. Usted debe mirar en el código de CryptoJS.

OriginalEl autor Nizar B. | 2014-12-28

2 Comentarios

  1. 9

    El problema es que en la CryptoJS código de una contraseña se utiliza para derivar la clave y el IV a ser utilizado para el cifrado AES, pero mcrypt sólo utiliza la clave para cifrar/descifrar. Esta información debe ser transmitida a php. Puesto que usted no quiere transmitir la contraseña, usted tiene que derivar la clave y IV de la misma manera en php.

    El siguiente código se deriva de la clave y IV a partir de una contraseña y la sal. Es modelada después de que el código en mi respuesta aquí (para obtener más información).

    function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5") {
        $targetKeySize = $keySize + $ivSize;
        $derivedBytes = "";
        $numberOfDerivedWords = 0;
        $block = NULL;
        $hasher = hash_init($hashAlgorithm);
        while ($numberOfDerivedWords < $targetKeySize) {
            if ($block != NULL) {
                hash_update($hasher, $block);
            }
            hash_update($hasher, $password);
            hash_update($hasher, $salt);
            $block = hash_final($hasher, TRUE);
            $hasher = hash_init($hashAlgorithm);
    
            //Iterations
            for ($i = 1; $i < $iterations; $i++) {
                hash_update($hasher, $block);
                $block = hash_final($hasher, TRUE);
                $hasher = hash_init($hashAlgorithm);
            }
    
            $derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4));
    
            $numberOfDerivedWords += strlen($block)/4;
        }
    
        return array(
            "key" => substr($derivedBytes, 0, $keySize * 4),
            "iv"  => substr($derivedBytes, $keySize * 4, $ivSize * 4)
        );
    }

    La sal se genera durante el proceso de cifrado en CryptoJS y debe ser enviado a php con el texto cifrado. Antes de invocar evpKDF la sal tiene que ser convertido a una cadena binaria de hex.

    $keyAndIV = evpKDF("Secret Passphrase", hex2bin($saltHex));
    $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, 
            $keyAndIV["key"], 
            hex2bin($cipherTextHex), 
            MCRYPT_MODE_CBC, 
            $keyAndIV["iv"]);

    Si sólo encryptedPassword.toString() fue enviada al servidor, a continuación, es necesario dividir la sal y el actual texto cifrado antes de su uso. El formato es una propiedad de OpenSSL-formato compatible con los 8 primeros bytes de ser «Curado__», el próximo 8 bytes aleatorios, la sal y el resto es el texto cifrado. Todo junto es codificada en Base64.

    function decrypt($ciphertext, $password) {
        $ciphertext = base64_decode($ciphertext);
        if (substr($ciphertext, 0, 8) != "Salted__") {
            return false;
        }
        $salt = substr($ciphertext, 8, 8);
        $keyAndIV = evpKDF($password, $salt);
        $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, 
                $keyAndIV["key"], 
                substr($ciphertext, 16), 
                MCRYPT_MODE_CBC, 
                $keyAndIV["iv"]);
    
        //unpad (PKCS#7)
        return substr($decryptPassword, 0, strlen($decryptPassword) - ord($decryptPassword[strlen($decryptPassword)-1]));
    }

    El mismo efecto se puede lograr con el OpenSSL extensión en lugar de Mcrypt:

    function decrypt($ciphertext, $password) {
        $ciphertext = base64_decode($ciphertext);
        if (substr($ciphertext, 0, 8) != "Salted__") {
            return false;
        }
        $salt = substr($ciphertext, 8, 8);
        $keyAndIV = evpKDF($password, $salt);
        $decryptPassword = openssl_decrypt(
                substr($ciphertext, 16), 
                "aes-256-cbc",
                $keyAndIV["key"], 
                OPENSSL_RAW_DATA, //base64 was already decoded
                $keyAndIV["iv"]);
    
        return $decryptPassword;
    }
    Código Similar puede ser encontrado en mis respuestas para Java y Python.
    aviso de Seguridad: Este código se proporciona para lograr la compatibilidad entre los diferentes lenguajes de programación. No es necesariamente de forma totalmente segura. Su seguridad depende de la complejidad y la longitud de la contraseña, porque de sólo una iteración y el uso de MD5. Yo recomendaría el uso de al menos un 20 caracteres de la contraseña con caracteres alfanuméricos, que está idealmente generado aleatoriamente.
    Muchas gracias @Artjom B.! Me gustaría poder darle +100. Esto fue muy útil.

    OriginalEl autor Artjom B.

  2. 0

    No se puede descifrar con una muestra aleatoria de la inicialización de los vectores que usted necesita para utilizar el mismo IV de los datos cifrados. También, si mal no recuerdo, AES valores predeterminados de 8 bits de la representación de los datos cifrados que necesitan ser manejadas cuidadosamente en la transferencia a través de HTTP.

    Una cosa, tengo un problema con md5. Cuando me pase el borrar la contraseña para ver el inicio de sesión del usuario, el hash md5 es igual a el hash md5 de la base de datos MySQL. Pero cuando estoy usando la contraseña descifrada, el md5 es diferente. Esto es raro ya que la clara cadena de contraseña es la misma que la cadena descifrada, y el hash md5 es diferente.

    OriginalEl autor symcbean

Dejar respuesta

Please enter your comment!
Please enter your name here