根据:
http://php.net/manual/en/function.mcrypt-decrypt.php
警告自PHP 7.1.0起,此函数(mcrypt-decrypt)已被弃用。 强烈不建议依赖此函数。
然后我不得不进行大量调查,直到发现一种使用JavaScript通过openssl加密并使用php解密的方法。
我遇到的唯一问题是当我发送长文本时。那是因为RSA在定义上支持有限长度的字符串。
https://security.stackexchange.com/questions/33434/rsa-maximum-bytes-to-encrypt-comparison-to-aes-in-terms-of-security/33445#33445
根据PKCS#1的定义,RSA加密有大小限制。使用通常的“v1.5填充”和2048位的RSA密钥,可加密的数据最大为245字节。不能再多。
例如,如果我使用1024位的私钥,则可以发送:
"José compró en Perú una vieja zampoña. Excusándose, Sofía tiró su whisky al desagüe de la banqueta."
没有更长的内容。如果我使用512位的私钥,就可以发送。
"José compró en Perú una vieja zampoña. Excusánd"
没有更长的内容。
当字符串过长时,JavaScript控制台会报告:“消息对于RSA过长”
因此,如果您想加密长字符串,则必须在javascript加密之前压缩和分割它们,在解密后在php上连接和解压缩它们,我认为zlib是一个很好的分割/连接解决方案,因为它在javascript和php上都受支持。
也许最好使用AES库而不是像https://github.com/brainfoolong/cryptojs-aes-php这样的库。
我的工作代码如下:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
$directorio = "/path/to/key/directory/apache/writable/";
$nombre_base = "llaves_php";
$encabezado_html = "";
$cuerpo_html = "";
list($privateKey, $pubKey) =
cargar_llaves_RSA($directorio, $nombre_base);
$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>
";
if (isset($_REQUEST['mensaje'])) {
openssl_private_decrypt( base64_decode($_REQUEST['mensaje'])
, $descifrado
, $privateKey);
$datos_html.= "
<h2>Descifrando con PHP</h2>
".$descifrado."
";
}
$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;
function cargar_llaves_RSA($directorio, $nombre_base) {
if ( !file_exists($directorio.$nombre_base.".crt")
|| !file_exists($directorio.$nombre_base.".pub")) {
list($privateKey, $pubKey) = crear_llaves_RSA($directorio.$nombre_base);
} else {
$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) {
$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) {
$retorno = htmlentities(stripslashes(var_export($valor, true)));
$retorno = "<pre>$retorno</pre>";
return $retorno;
}
?>
目录树必须长成这样:
├── script.php
└── lib
└── jsencrypt.js
需要一个目录,由php在公共区域之外进行写入,并命名为
/path/to/key/directory/apache/writable/