2009-03-04 165 views
7

Me gustaría encriptar en Javascript y luego descifrarlo en PHP. Existen implementaciones de RSA para Javascript y PHP, pero no son compatibles. No puedo descifrar en PHP correctamente lo que cifré con Javascript.Encriptación/descifrado RSA compatible con Javascript y PHP

¿Alguien sabe una biblioteca/código que funcione tanto con Javascript como con PHP?

Gracias.

+1

Parece que estás considerando esto para el cifrado de datos confidenciales entre un cliente y un servidor. Se te advierte que esto NO ofrecerá CUALQUIER seguridad contra un ataque de hombre en el medio en el que se verán comprometidos los datos que pasen. Use HTTPS para un cifrado de extremo a extremo seguro y autenticado. – deed02392

Respuesta

1

Si configura su servidor para usar SSL, entonces puede tener una transmisión encriptada a través de ajax usando https. Esa es probablemente la mejor forma de cifrar datos entre javascript y php. Si quiere hacerlo usted mismo, existe la gran posibilidad de que se arruine en alguna parte y el sistema no sea seguro.

Google sobre cómo configurar https para su servidor.

0

Supongo que tiene un motivo válido para hacer eso, aparte de hacer https usted mismo, entonces yo diría que si se apega a los estándares, debería ser capaz de descifrar fácilmente con cualquier tecnología que soporte estos estándares: es decir, debería trabajo

Por ejemplo, si cifras tus datos en formato PKCS # 7, asegúrate de que tu biblioteca php sepa que los datos de entrada son PKCS # 7.

También asegúrese de que su clave de cifrado no esté codificada entre el servidor y el cliente. ¿Intentó descifrar sus datos con su biblioteca de JavaScript?

la esperanza que esto puede ayudar ...

0

Tal vez usted puede ayudar al poner el código que está utilizando para ambos js y php.

Además, tal vez podría ser más específico sobre por qué necesita usar js y php. Tal vez podrías usar solo php y AJAX (para consultar la misma función php) donde estabas usando js.

+0

Creo que el OP intenta enviar algo como una contraseña al servidor en forma cifrada. Si enviara la contraseña a una función php usando AJAX, entonces aún estaría enviando la contraseña de texto sin formato a la llamada AJAX y luego encriptarlo en el método php ya no tendría sentido – lugte098

7

Aquí es una biblioteca de cifrado JavaScript RSA: http://www.ohdave.com/rsa/

Y creo que se podría utilizar algo como esta clase para descifrar la cadena cifrada generada - http://www.phpclasses.org/browse/package/4121.html

Avisadme si logra conseguir este trabajo en conjunto, como yo mismo estoy investigando este tema (de hecho, encontré esta publicación buscando esta respuesta yo mismo: P).

Editar: Mira, yo también he encontrado este - http://www.sematopia.com/?p=275 - parece estar relacionado con los dos anteriores, así ...

0

No soy uno a sonar mi molino, pero tengo un proyecto en github.com que realizará esta funcionalidad.

Se genera una clave privada en el servidor, una clave pública y el certificado de pkcs # 7 también se derivan de la clave privada. La clave pública se envía al cliente, momento en el que cada elemento del formulario asociado con el formulario especificado se cifra antes de enviarse al servidor.

Es 100% compatible con OpenSSL ya que utiliza la extensión PHP OpenSSL para generar, cifrar y descifrar datos.

https://github.com/jas-/jQuery.pidCrypt/

Este proyecto no es tan seguro como PGP porque el JavaScript no va a firmar y cifrar mensajes de correo electrónico hasta que los datos del formulario se envía al servidor, pero los datos del formulario que se debe cifrar y ni firmado se cifra usando cifrado de clave pública RSA antes de ser enviado al servidor.

Una vez más, el proyecto no está completo en términos de autentificación y firma de correo electrónico, pero para el cifrado de formularios ordinarios con una clave pública funciona muy bien.

5

Pruebe el siguiente ejemplo simple.

Está utilizando un código abierto biblioteca de Javascript https://github.com/ziyan/javascript-rsa

HTML/Javascript:

<script language="JavaScript" type="text/javascript" src="jsbn.js"></script> 
<script language="JavaScript" type="text/javascript" src="rsa.js"></script> 

<script language="JavaScript"> 

    function encryptData(){ 

     //Don't forget to escape the lines: 
     var pem="-----BEGIN PUBLIC KEY-----\ 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfmlc2EgrdhvakQApmLCDOgP0n\ 
NERInBheMh7J/r5aU8PUAIpGXET/8+kOGI1dSYjoux80AuHvkWp1EeHfMwC/SZ9t\ 
6rF4sYqV5Lj9t32ELbh2VNbE/7QEVZnXRi5GdhozBZtS1gJHM2/Q+iToyh5dfTaA\ 
U8bTnLEPMNC1h3qcUQIDAQAB\ 
-----END PUBLIC KEY-----"; 

     var key = RSA.getPublicKey(pem); 

     element=document.getElementById('password'); 
     element.value=RSA.encrypt(element.value, key); 
    } 
</script> 

<form method='POST' id='txtAuth' onsubmit='encryptData()'> 
    <input type='text' name='username'/> 
    <input type='password' name='password' id='password' placeholder="password"/> 
    <input name='submit' type='submit' value='Submit'> 
</form> 

PHP:

<?php 

if (isset($_POST['password'])) { 

    //Load private key: 
    $private = "-----BEGIN RSA PRIVATE KEY----- 
    MIICXAIBAAKBgQDfmlc2EgrdhvakQApmLCDOgP0nNERInBheMh7J/r5aU8PUAIpG 
    XET/8+kOGI1dSYjoux80AuHvkWp1EeHfMwC/SZ9t6rF4sYqV5Lj9t32ELbh2VNbE 
    /7QEVZnXRi5GdhozBZtS1gJHM2/Q+iToyh5dfTaAU8bTnLEPMNC1h3qcUQIDAQAB 
    AoGAcbh6UFqewgnpGKIlZ89bpAsANVckv1T8I7QT6qGvyBrABut7Z8t3oEE5r1yX 
    UPGcOtkoRniM1h276ex9VtoGr09sUn7duoLiEsp8aip7p7SB3X6XXWJ9K733co6C 
    dpXotfO0zMnv8l3O9h4pHrrBkmWDBEKbUeuE9Zz7uy6mFAECQQDygylLjzX+2rvm 
    FYd5ejSaLEeK17AiuT29LNPRHWLu6a0zl923299FCyHLasFgbeuLRCW0LMCs2SKE 
    Y+cIWMSRAkEA7AnzWjby8j8efjvUwIWh/L5YJyWlSgYKlR0zdgKxxUy9+i1MGRkn 
    m81NLYza4JLvb8/qjUtvw92Zcppxb7E7wQJAIuQWC+X12c30nLzaOfMIIGpgfKxd 
    jhFivZX2f66frkn2fmbKIorCy7c3TIH2gn4uFmJenlaV/ghbe/q3oa7L0QJAFP19 
    ipRAXpKGX6tqbAR2N0emBzUt0btfzYrfPKtYq7b7XfgRQFogT5aeOmLARCBM8qCG 
    tzHyKnTWZH6ff9M/AQJBAIToUPachXPhDyOpDBcBliRNsowZcw4Yln8CnLqgS9H5 
    Ya8iBJilFm2UlcXfpUOk9bhBTbgFp+Bv6BZ2Alag7pY= 
    -----END RSA PRIVATE KEY-----"; 
    if (!$privateKey = openssl_pkey_get_private($private)) die('Loading Private Key failed'); 

    //Decrypt 
    $decrypted_text = ""; 
    if (!openssl_private_decrypt(base64_decode($_POST['password']), $decrypted_text, $privateKey)) die('Failed to decrypt data'); 

    //Decrypted :) 
    var_dump($decrypted_text); 

    //Free key 
    openssl_free_key($privateKey); 
} 
?> 

Enjoy!

+1

Para futuros lectores: David.Pedir sugirió en una edición rechazada a esta respuesta que esto debería agregarse también al encabezado: '' – Tieme

+0

Utilice este proyecto con PHP Awser funciona como un encanto para mí https://github.com/travist/jsencrypt/ –

0

Encuentro esta biblioteca jsencrypt (http://travistidwell.com/jsencrypt), después de 2 días intentando obtener mi solución.

El único problema que tengo es cuando envío un texto largo. Eso es porque RSA, por definición, admite cadenas de longitud limitada.

https://security.stackexchange.com/questions/33434/rsa-maximum-bytes-to-encrypt-comparison-to-aes-in-terms-of-security/33445#33445

RSA, tal como se define por PKCS # 1, encripta "mensajes" de tamaño limitado. Con el "relleno v1.5" comúnmente utilizado y una clave RSA de 2048 bits, el tamaño máximo de datos que se puede cifrar con RSA es de 245 bytes. No más.

decir Si uso private_key_bits de 1024 puedo enviar

"José compró en Perú una vieja zampoña. Excusándose, Sofía tiró su whisky al desagüe de la banqueta." 

nada más. Si uso private_key_bits de 512 puedo enviar

"José compró en Perú una vieja zampoña. Excusánd" 

nada más.

En largas cadenas JavaScript consola de informes: "El mensaje es demasiado largo para RSA"

Entonces, si usted quiere cifrar cadenas largas se debe comprimir y dividirlos antes de JavaScript cifrado y después de descifrado unirse y descomprimir en php, creo zlib es una buena solución para split/join porque es compatible con javascript y php.

Mi código de trabajo es el siguiente:

<?php 
    //------------------------------------------------------------ 
    // Global Settings. 
    //------------------------------------------------------------ 
    ini_set('display_errors', 1); 
    error_reporting(E_ALL); 
    $directorio = "/path/to/key/directory/apache/writable/"; 
    $nombre_base = "llaves_php"; 

    //------------------------------------------------------------ 
    // Initialization. 
    //------------------------------------------------------------ 
    $encabezado_html = ""; 
    $cuerpo_html = ""; 

    //------------------------------------------------------------ 
    // Loading keys 
    //------------------------------------------------------------ 
    list($privateKey, $pubKey) = 
     cargar_llaves_RSA($directorio, $nombre_base); 

    //------------------------------------------------------------ 
    // Form that uses javascript to encrypt data. 
    // (it uses only the public key) 
    //------------------------------------------------------------ 
    $librerias_html = " 
     <script type='text/javascript' 
       src='https://ajax.googleapis.com/ajax/libs/". 
        "jquery/3.2.1/jquery.min.js'></script> 
     <script type='text/javascript' 
       src='lib/jsencrypt.js'></script> 
     "; 

    $pubKey_html = htmlentities($pubKey); 
    $datos_html = " 
     <h2>Cifrando con Javascript</h2> 
     <input type='text' id='mensaje' /> 
     <br /> 
     <button id='ENVIAR'>Enviar</button> 
     <br /> 
     <textarea id='pubkey' style='display: none;'>". 
     $pubKey_html. 
     "</textarea> 
     <script type='text/javascript'> 
      $('#ENVIAR').click(function() { 
       var codificador = new JSEncrypt(); 
       codificador.setKey($('#pubkey').val()); 
       var cifrado = codificador.encrypt($('#mensaje').val()); 
       window.open('?mensaje=' + encodeURIComponent(cifrado) 
          , '_top'); 
      }); 
     </script> 
     "; 

    //------------------------------------------------------------ 
    // Decrypting using php (it uses only the privateKey) 
    //------------------------------------------------------------ 
    if (isset($_REQUEST['mensaje'])) { 
     openssl_private_decrypt(base64_decode($_REQUEST['mensaje']) 
           , $descifrado 
           , $privateKey); 
     $datos_html.= " 
      <h2>Descifrando con PHP</h2> 
      ".$descifrado." 
      "; 
    } 

    //------------------------------------------------------------ 
    // HTML DISPLAY 
    //------------------------------------------------------------ 
    $encabezado_html.= "<title>Receptor de mensaje cifrado</title>" 
        . $librerias_html; 

    $cuerpo_html.= $datos_html; 

    $contenido = "<head>$encabezado_html</head><body>$cuerpo_html</body>"; 
    $contenido = "<html>$contenido</html>"; 
    print $contenido; 

//============================================================ 
//============================================================ 
// Functions 
//============================================================ 
//============================================================ 

    //------------------------------------------------------------ 
    function cargar_llaves_RSA($directorio, $nombre_base) { 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    // PROPÓSITO: Genera o carga desde archivos las llaves RSA 
    // ENTRADAS: 
    // $directorio: Directorio donde se encuentran los archivos. 
    // $nombre_base: Nombre, sin extensión, de los archivos con 
    //    las llaves. 
    // SALIDAS: 
    //------------------------------------------------------------ 
     if ( !file_exists($directorio.$nombre_base.".crt") 
      || !file_exists($directorio.$nombre_base.".pub")) { 
      list($privateKey, $pubKey) = crear_llaves_RSA($directorio.$nombre_base); 
     } else { 
      //------------------------------------------------------------ 
      // CARGA DE LLAVES RSA ARCHIVADAS 
      //------------------------------------------------------------ 
      $privateKey = file_get_contents($directorio.$nombre_base.".crt"); 
     if (!$privKey = openssl_pkey_get_private($privateKey)) 
      die('Loading Private Key failed'); 
      $pubKey = file_get_contents($directorio.$nombre_base.".pub"); 
     } 

    return array($privateKey, $pubKey); 
    } 

    //------------------------------------------------------------ 
    function crear_llaves_RSA($ruta_base) { 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    // PROPÓSITO: 
    // generacion de llaves RSA en php 
    // ENTRADAS: 
    // $ruta_base: Ruta de los archivos a generar sin extensión. 
    // SALIDAS: 
    // Se generarán dos archivos, uno con la llave privada con 
    // extensión .crt, el otro con llave pública con extensión 
    // .pub; la función retorna tanto la llave pública como la 
    // privada en un arreglo. 
    //------------------------------------------------------------ 
     $config = array(
      "private_key_bits" => 1024, 
      "private_key_type" => OPENSSL_KEYTYPE_RSA, 
     ); 

     $llavePrivadaCruda = openssl_pkey_new($config); 
     openssl_pkey_export_to_file($llavePrivadaCruda, $ruta_base.".crt"); 
     $privateKey = file_get_contents($ruta_base.".crt"); 
     openssl_pkey_export($llavePrivadaCruda, $privKey); 

     $pubKeyData = openssl_pkey_get_details($llavePrivadaCruda); 
     $pubKey = $pubKeyData["key"]; 
     file_put_contents($ruta_base.".pub", $pubKey); 
     openssl_free_key($llavePrivadaCruda); 

    return array($privateKey, $pubKey); 
    } 

    //------------------------------------------------------------ 
    function Mostrar($valor) { 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    // PROPÓSITO: Genera el código HTML para presentar una 
    // variable embebida en la página. 
    // ENTRADAS: 
    // $valor: el valor a presentar. 
    // SALIDAS: código html que permite visualizar la variable. 
    //------------------------------------------------------------ 
     $retorno = htmlentities(stripslashes(var_export($valor, true))); 
     $retorno = "<pre>$retorno</pre>"; 
     return $retorno; 
    } 

?> 

Directorio árbol debe ve así:

├── script.php 
└── lib 
    └── jsencrypt.js 

y un directorio escribible por PHP fuera de la zona pública denominada

/path/to/key/directory/apache/writable/ 

Cuestiones relacionadas