RSA Encryption / Decryption compatible with Javascript and PHP

I would like to encrypt in Javascript and then decrypt in PHP. RSA implementations exist for Javascript and PHP, but they are incompatible. I cannot correctly decrypt in PHP what I encrypted using Javascript.

Does anyone know a library / code that will work with both Javascript and PHP?

Thanks.

+7
javascript php rsa
source share
7 answers

Here is the RSA JavaScript encryption library: http://www.ohdave.com/rsa/

And I think you could use something like this class to decrypt the generated encrypted string - http://www.phpclasses.org/browse/package/4121.html

Let me know if you can handle this collaboration, as I am studying this topic myself (I really found this post looking for this answer myself: P).

Edit: Look, I also found this - http://www.sematopia.com/?p=275 - similar to the previous two ...

+7
source share

Try the following simple example.

Used open source javascript library 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 it!

+5
source share

If you configured the server to use SSL, you can encrypt the transfer through ajax using https. This is probably the best way to encrypt data between javascript and php. If you want to do it yourself, there is a good chance that you will get lost somewhere and the system will not be safe.

Google on how to configure https for your server.

+1
source share

I assume that you have a good reason to do it differently than doing https yourself, so I would say that if you adhere to standards, you should be able to easily decrypt any technology that supports these standards: that is, it should work

For example, if you encrypt your data in PKCS # 7 format, make sure your php library knows that the input is PKCS # 7.

Also make sure your encryption key is not scrambled between the server and the client. Have you tried to decrypt your data using javascript library?

Hope this helps ...

0
source share

Perhaps you can help by putting the code you use for js and php.

Also, perhaps you can clarify why you need to use js and php. Perhaps you could only use php and AJAX (to request the same php function) where you used js.

0
source share

I'm not one of those who want to use their own horn, but I have a project on github.com that will perform this function.

A private key is created on the server, the public key and certificate pkcs # 7 are also inferred from the private key. The public key is sent to the client, and at this time, each element of the form associated with the specified form is encrypted before being sent to the server.

It is 100% compatible with OpenSSL because it uses the PHP OpenSSL extension to generate, encrypt and decrypt data.

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

This project is not as secure as PGP because JavaScript will not sign and encrypt emails until the form data is sent to the server, but the form data that must be encrypted and / or signed is encrypted using open encryption RSA key previously for sending to the server.

Again, the project is not complete in terms of authentication and email signature, but for normal encryption of the form using the public key, it works very well.

0
source share

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/ 

0
source share

All Articles