w3schools tag tab color attribute javascript php rsa public-key pgp

javascript - tag - title html w3schools



Cifre en Javascript, descifre en PHP, usando criptografía de clave pública (5)

Me gustaría cifrar en JavaScript, descifrar en PHP, usando criptografía de clave pública. He estado tratando de encontrar bibliotecas que puedan lograr esto, pero tengo problemas.

Actualmente estoy buscando en openpgpjs , pero necesito asistencia en todos los navegadores, e incluso la página de prueba tiene errores en el único listado como navegador compatible (Google Chrome).

Notas sobre el objetivo final:

La conexión TCP ya está protegida por SSL. El objetivo principal de esta capa de protección es la defensa contra el registro intencional o no intencional del servidor web, los volcados de memoria, etc.

En el lado de PHP, se generará una clave privada temporal (expirará después de un breve período de tiempo). La persona que llama (en Javascript) es responsable de solicitar una nueva clave pública cuando caduque. El motivo de la caducidad de la clave privada es evitar el descifrado de datos cifrados registrados, en caso de que el servidor que almacena la clave privada se vea comprometido posteriormente.

Escenario comprometido de los servidores: alguien obtiene sus manos en copias de seguridad de todas las máquinas, excepto el servidor de la base de datos (y no puede acceder a la base de datos debido al cortafuegos, incluso si descubre el usuario y la contraseña). Dado que la clave privada que cifró los datos registrados ya no existe, no hay nada que el atacante pueda hacer.


Echa un vistazo a node-rsa .

Es un módulo node.js

Este módulo proporciona acceso a las rutinas de clave pública RSA desde OpenSSL. El soporte se limita a RSAES-OAEP y el cifrado con una clave pública, el descifrado con una clave privada.

Tal vez usted puede portarlo para ejecutarse en el navegador.

ACTUALIZAR

Biblioteca del lado del cliente RSA para javascript: (pidcrypt se ha descontinuado oficialmente y el dominio del sitio web ha caducado; consulte la respuesta de @jack que contiene las mismas bibliotecas que contiene pidcrypt) . https://www.pidder.com/pidcrypt/?page=rsa

Componente del lado del servidor PHP: http://phpseclib.sourceforge.net/

¡Buena suerte!


Ejemplo de uso de RSA para https://www.pidder.com/pidcrypt/?page=rsa (js) y http://phpseclib.sourceforge.net/ (php).

No reutilice la clave privada en este ejemplo de trabajo.

cifrado pidCrypt

//From the pidCrypt example sandbox function certParser(cert) { var lines = cert.split(''/n''); var read = false; var b64 = false; var end = false; var flag = ''''; var retObj = { }; retObj.info = ''''; retObj.salt = ''''; retObj.iv; retObj.b64 = ''''; retObj.aes = false; retObj.mode = ''''; retObj.bits = 0; for (var i = 0; i < lines.length; i++) { flag = lines[i].substr(0, 9); if (i == 1 && flag != ''Proc-Type'' && flag.indexOf(''M'') == 0)//unencrypted cert? b64 = true; switch (flag) { case ''-----BEGI'': read = true; break; case ''Proc-Type'': if (read)retObj.info = lines[i]; break; case ''DEK-Info:'': if (read) { var tmp = lines[i].split('',''); var dek = tmp[0].split('': ''); var aes = dek[1].split(''-''); retObj.aes = (aes[0] == ''AES'') ? true : false; retObj.mode = aes[2]; retObj.bits = parseInt(aes[1]); retObj.salt = tmp[1].substr(0, 16); retObj.iv = tmp[1]; } break; case '''': if (read)b64 = true; break; case ''-----END '': if (read) { b64 = false; read = false; } break; default : if (read && b64)retObj.b64 += pidCryptUtil.stripLineFeeds(lines[i]); } } return retObj; } var strCreditCardPublicKey="-----BEGIN PUBLIC KEY-----/nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC//tI7cw+gnUPK2LqWp50XboJ1i/njrLDn+4//gPOe+pB5kz4VJX2KWwg9iYMG9UJ1M+AeN33qT7xt9ob2dxgtTh7Mug2S/nn1TLz4donuIzxCmW+SZdU1Y+WNDINds194hWsAVhMC1ClMQTfldUGzQnI5sXvZTF/nJWp//9jheCNLDRIkAnQIDAQAB/n-----END PUBLIC KEY-----/n"; var objParams=certParser(strCreditCardPublicKey); var binaryPrivateKey=pidCryptUtil.decodeBase64(objParams.b64); var rsa=new pidCrypt.RSA(); var asn=pidCrypt.ASN1.decode(pidCryptUtil.toByteArray(key)); var tree=asn.toHexTree(); rsa.setPublicKeyFromASN(tree); var strHexSensitiveDataEncrypted=rsa.encrypt("4111111111111111"); var strBase64SensitiveDataEncrypted=pidCryptUtil.fragment(pidCryptUtil.encodeBase64(pidCryptUtil.convertFromHex(strHexSensitiveDataEncrypted)), 64)) console.log(strBase64SensitiveDataEncrypted);

.

desencriptación de phpseclib

require_once("Crypt/RSA.php"); function decrypt($strBase64CipherText) { //CRYPT_RSA_MODE_INTERNAL is slow //CRYPT_RSA_MODE_OPENSSL is fast, but requires openssl to be installed, configured and accessible. define("CRYPT_RSA_MODE", CRYPT_RSA_MODE_INTERNAL); $rsa=new Crypt_RSA(); //$strPrivateKey=file_get_contents("private.pem"); //This private key is for example purposes //DO NOT REUSE $strPrivateKey="-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDBNHK7R2CCYGqljipbPoj3Pwyz4cF4bL5rsm1t8S30gbEbMnKn 1gpzteoPlKp7qp0TnsgKab13Fo1d+Yy8u3m7JUd/sBrUa9knY6dpreZ9VTNul8Bs p2LNnAXOIA5xwT10PU4uoWOo1v/wn8eMeBS7QsDFOzIm+dptHYorB3DOUQIDAQAB AoGBAKgwGyxy702v10b1omO55YuupEU3Yq+NopqoQeCyUnoGKIHvgaYfiwu9sdsM ZPiwxnqc/7Eo6Zlw1XGYWu61GTrOC8MqJKswJvzZ0LrO3oEb8IYRaPxvuRn3rrUz K7WnPJyQ2FPL+/D81NK6SH1eHZjemb1jV9d8uGb7ifvha5j9AkEA+4/dZV+dZebL dRKtyHLfbXaUhJcNmM+04hqN1DUhdLAfnFthoiSDw3i1EFixvPSiBfwuWC6h9mtL CeKgySaOkwJBAMSdBhn3C8NHhsJA8ihQbsPa6DyeZN+oitiU33HfuggO3SVIBN/7 HmnuLibqdxpnDOtJT+9A+1D29TkNENlTWgsCQGjVIC8xtFcV4e2s1gz1ihSE2QmU JU9sJ3YeGMK5TXLiPpobHsnCK8LW16WzQIZ879RMrkeDT21wcvnwno6U6c8CQQCl dsiVvXUmyOE+Rc4F43r0VRwxN9QI7hy7nL5XZUN4WJoAMBX6Maos2Af7NEM78xHK SY59+aAHSW6irr5JR351AkBA+o7OZzHIhvJfaZLUSwTPsRhkdE9mx44rEjXoJsaT e8DYZKr84Cbm+OSmlApt/4d6M4YA581Os1eC8kopewpy -----END RSA PRIVATE KEY----- "; $strPrivateKey=preg_replace("/[ /t]/", "", $strPrivateKey);//this won''t be necessary when loading from PEM $rsa->loadKey($strPrivateKey); $binaryCiphertext=base64_decode($strBase64CipherText); $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); $strBase64DecryptedData=$rsa->decrypt($binaryCiphertext); return base64_decode($strBase64DecryptedData); } //The pidCrypt example implementation will output a base64 string of an encrypted base64 string which contains the original data, like this one: $strBase64CipherText="JDlK7L/nGodDJodhCj4uMw0/LW329HhO2EvxNXNUuhe+C/PFcJBE7Gp5GWZ835fNekJDbotsUFpLvP187AFAcNEfP7VAH1xLhhlB2a9Uj/z4Hulr4E2EPs6XgvmLBS3MwiHALX2fES5hSKY/sfSUssRH10nBHHO9wBLHw5mRaeg="; $binaryDecrypted=decrypt($strBase64CipherText); //should output ''4111111111111111'' var_export($binaryDecrypted);



He usado algo similar para mi página de inicio de sesión; encripta las credenciales de inicio de sesión usando la información de clave pública dada (N, e) que se puede descifrar en PHP.

Utiliza los siguientes archivos que son parte de JSBN :

  • jsbn.js - para trabajar con grandes enteros
  • rsa.js - solo para cifrado RSA (usa jsbn.js)
  • rng.js - colector básico de entropía
  • prng4.js - ARC4 RNG backend

Para cifrar los datos:

$pk = ''-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----''; $kh = openssl_pkey_get_private($pk); $details = openssl_pkey_get_details($kh); function to_hex($data) { return strtoupper(bin2hex($data)); } ?> <script> var rsa = new RSAKey(); rsa.setPublic(''<?php echo to_hex($details[''rsa''][''n'']) ?>'', ''<?php echo to_hex($details[''rsa''][''e'']) ?>''); // encrypt using RSA var data = rsa.encrypt(''hello world''); </script>

Así es como se decodificarían los datos enviados:

$kh = openssl_pkey_get_private($pk); $details = openssl_pkey_get_details($kh); // convert data from hexadecimal notation $data = pack(''H*'', $data); if (openssl_private_decrypt($data, $r, $kh)) { echo $r; }


Tenga cuidado con la implementación de RSA. De hecho, probablemente no deberías usar RSA en absoluto. (¡ Utilice libsodium en su lugar! )

Incluso si está utilizando una biblioteca (p. Ej., La extensión OpenSSL de PHP directamente o, hasta hace poco, Zend/Crypt ), todavía hay muchas cosas que pueden salir mal. En particular:

  • El relleno PKCS1v1.5, que es el valor por defecto (y en muchos casos el único modo de relleno compatible), es vulnerable a una clase de ataques de texto cifrado elegidos llamado oráculo de relleno. Esto fue descubierto por primera vez por Daniel Bleichenbacher. En 1998.
  • RSA no es adecuado para cifrar mensajes grandes, por lo que lo que suelen hacer los implementadores es tomar un mensaje largo, dividirlo en bloques de tamaño fijo y cifrar cada bloque por separado. Esto no solo es lento, sino que es análogo al temido modo ECB para la criptografía de clave simétrica.

Lo mejor que puedes hacer, con Libsodium

Es posible que desee leer JavaScript Cryptography Considered Harmful unas cuantas veces antes de seguir esta ruta. Pero dicho eso ...

  1. Use TLSv1.2 con HSTS y HPKP, preferiblemente con ChaCha20-Poly1305 y / o AES-GCM y un certificado ECDSA-P256 (importante: cuando IETF christens Curve25519 y Ed25519, cambien a eso).
  2. Agrega libsodium.js a tu proyecto.
  3. Use crypto_box_seal() con una clave pública para cifrar sus mensajes, del lado del cliente.
  4. En PHP, use /Sodium/crypto_box_seal_open() con la clave secreta correspondiente para que la clave pública descifre el mensaje.

Necesito usar RSA para resolver este problema.

Por favor no lo hagas La criptografía de curva elíptica es más rápida, más sencilla y mucho más fácil de implementar sin canales laterales. La mayoría de las bibliotecas ya lo hacen por ti. (¡Libsodium!)

¡Pero realmente quiero usar RSA!

Bien, siga estas recomendaciones de la carta y no llore a cuando cometa un error (como lo hizo SaltStack ) que hace que su criptografía sea inútil.

Una opción (que no viene con una implementación complementaria de JavaScript, y por favor no solicite una) que apunta a proporcionar un cifrado RSA simple y fácil es paragonie/easyrsa .

  • Evita los oráculos de relleno utilizando RSA-OAEP con MGF1 + SHA256 en lugar de PKCS1v1.5.
  • Evita el modo ECB por un diseño de protocolo inteligente:

El protocolo de cifrado EasyRSA

  1. EasyRSA genera una clave aleatoria de 128 bits para la criptografía de clave simétrica (a través de AES).
  2. Su mensaje de texto sin formato está cifrado con cifrado defuse/php-encryption .
  3. Su clave AES está cifrada con RSA, proporcionada por phpseclib , usando el modo correcto (mencionado anteriormente).
  4. Esta información se incluye como una cadena simple (con una suma de comprobación).

Pero, realmente, si encuentra un caso de uso válido para la criptografía de clave pública, en su lugar desea libsodium.