I find this jsencrypt library ( http://travistidwell.com/jsencrypt ), after 2 days I got my solution.
The only problem I encountered is when I post a long text. This is because RSA, by definition, supports strings with a limited length.
https://security.stackexchange.com/questions/33434/rsa-maximum-bytes-to-encrypt-comparison-to-aes-in-terms-of-security/33445#33445
RSA, as defined by PKCS # 1, encrypts "messages" of a limited size. With the commonly used "add-on v1.5" and a 2048-bit RSA key, the maximum size of data that can be encrypted using RSA is 245 bytes. More.
i.e. If I use private_key_bits 1024, I can send
"José compró en Perú una vieja zampoña. Excusándose, Sofía tiró su whisky al desagüe de la banqueta."
nothing more. If I use private_key_bits from 512, I can send
"José compró en Perú una vieja zampoña. Excusánd"
Nothing more.
In the long line of the JavaScript console report: "The message is too long for RSA"
Then, if you want to encrypt long strings, you have to compress and split them before javascript encryption, and after decrypting, join and overclock in php, I think zlib is a good solution for split / join because it is supported in javascript and php.
My working code is as follows:
<?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; } ?>
The directory tree should look like this:
├── script.php └── lib └── jsencrypt.js
and a directory writable via php outside the public zone named
/path/to/key/directory/apache/writable/