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/
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