我有一个由几个网站使用的PHP端点。在将数据发布到端点时,站点使用加密的标头来标识各种信息。这些站点使用标准的PHP mcrypt_ecb
函数,端点解密变量,如下所示:
$var = trim(mcrypt_ecb(MCRYPT_DES, $key, base64_decode($input), MCRYPT_DECRYPT)));
我真的没有太多机会改变PHP端点,尽管如果mcrypt_ecb
不能很好地发挥作用,我可以设想另一个端点。
我现在有一个PhoneGap应用程序,它还需要发送加密的标头。 Phonegap只能真正使用javascript POST到远程服务器。我看过Google CryptoJS试图在base64库旁边尝试实现这一点。请注意,该键与上面的$ key var相同。
var encrypted = CryptoJS.DES.encrypt(user.email, key).toString();
var base64 = base64.encode(encrypted);
问题是当通过mcrypt_ecb
传递时,加密的字符串(我尝试过没有base64编码/解码)是垃圾。显然有三种DES加密的不同方法?
如何在JavaScript中创建mcrypt_ecb
兼容的加密字符串?
答案 0 :(得分:1)
按照: http://php.net/manual/en/function.mcrypt-decrypt.php
警告此功能(mcrypt-decrypt)自PHP 7.1.0起已废弃。非常不鼓励依赖此功能。
然后我不得不进行很多调查,直到我发现一种通过javascript使用openssl加密并使用php解密的方法。
我遇到的唯一问题是发送长文本。这是因为根据定义,RSA支持有限长度的字符串。
由PKCS#1定义的RSA加密有限大小的“消息”。同 常用的“v1.5填充”和2048位RSA密钥,最大值 可以用RSA加密的数据大小是245字节。没有了。
即。 如果我使用1024的private_key_bits,我可以发送
"José compró en Perú una vieja zampoña. Excusándose, Sofía tiró su whisky al desagüe de la banqueta."
不再。 如果我使用512的private_key_bits,我可以发送
"José compró en Perú una vieja zampoña. Excusánd"
不再。
在长字符串上JavaScript控制台报告:“消息对于RSA来说太长了”
然后,如果你想加密长字符串,你必须在javascript加密之前压缩和拆分它们,在解密后加入并解压缩php,我认为zlib是一个很好的解决方案,因为它支持javascript和php。 / p>
使用AES库而不是像https://github.com/brainfoolong/cryptojs-aes-php
这样的库可能更好我的工作代码如下:
<?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;
}
?>
目录树必须如下所示:
├── script.php
└── lib
└── jsencrypt.js
和一个名为
的公共区域外的php可写的目录/path/to/key/directory/apache/writable/
答案 1 :(得分:0)
我使用了相同的库。必须确保des()
结果被修剪,因为后面有一些奇怪的字符并且它不匹配。
$password = trim(des("12345678", hexToString("1212121121"), 0, 1, null));
希望它有所帮助。
答案 2 :(得分:0)
此答案由Op发布为edit to the question。虽然被问到post as an answer,但它仍然是对原始问题的修改。
我通过使用不同的javascript加密库解决了这个问题。方法如下:
我使用了Paul Tero更简单的DES库用于javascript和标准的PHP解密函数。
使用Javascript:
var key = '12345678';
var encrypted = stringToHex(des(key, 'This is something private', 1));
注意事项:
stringToHex
包含在DES javascript代码中。PHP
$key = '12345678'
$unencrypted = trim(mcrypt_decrypt(MCRYPT_DES
, $key
, safeHexToString($encrypted)
, MCRYPT_MODE_ECB))
使用此辅助函数:
/**
*
* Convert input HEX encoded string to a suitable format for decode
* // Note: JS generates strings with a leading 0x
*
* @return string
*/
function safeHexToString($input)
{
if(strpos($input, '0x') === 0)
{
$input = substr($input, 2);
}
return hex2bin($input);
}
那为我做了。具有前导'0x'的javascript十六进制编码字符串对我来说引起了一些问题,因为我以特别愚蠢的方式进行调试。
所以我希望这有帮助。