如何解密 PHP 中使用 JSEncrypt 加密的数据

ljc*_*fty 3 php encryption-asymmetric cryptojs php-openssl jsencrypt

我试图通过使用对称和非对称加密来保护 JS 前端和 PHP 后端之间的通信。我正在客户端上创建一个对称密钥,并使用服务器的公钥和 JSEncrypt 对其进行加密,然后将其发送到服务器以供将来使用。但是,当我在服务器端获取数据时,我遇到了困难。openssl_open 需要一个信封来解密对称密钥,我什至不确定信封中应该包含什么数据。我的印象是信封是用公钥加密的对称密钥,但使用它并没有起作用。我还尝试了不同的解码组合,因为我读到 JSEncrypt 以 64 进制编码消息,以十六进制编码密钥,但这些尝试也是徒劳的。

\n\n

JS加密代码:

\n\n
let pub = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----";\n\n//I have a function that just creates a random string of characters\nlet key = generateKey(32);\nlet aesData = CryptoJS.AES.encrypt( "test", key );\nlet symKey = aesData.key + ":::" + aesData.iv;\nlet msg = aesData.toString();\n\nlet rsa = new JSEncrypt();\nrsa.setPublicKey( pub );\nlet cryptKey = rsa.encrypt( symKey );\n\n//I\'m passing the data through a hidden form field\n$("#key").val(cryptKey + ":::" + msg);\n
Run Code Online (Sandbox Code Playgroud)\n\n

PHP解密代码:

\n\n
$key = openssl_get_privatekey( file_get_contents( $_SERVER["PRIV_KEY"]) );\n$encryptedKey = explode( ":::", $msg )[0];\n$realMsg = base64_decode(explode( ":::", $msg )[1]);\n\nopenssl_open($realMsg, $decrypted, $encryptedKey, $key);\nreturn $decrypted;\n
Run Code Online (Sandbox Code Playgroud)\n\n

上面的代码没有输出任何内容,因为 openssl_open 调用失败(返回 false)。当我对 $encryptedKey 变量进行 Base 64 解码时,我得到:

\n\n
\xef\xbf\xbdvEi\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdp\xce\x95\xef\xbf\xbd\xef\xbf\xbdd_\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd@\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xec\x9a\xb2JE\xef\xbf\xbd\xef\xbf\xbd\n
Run Code Online (Sandbox Code Playgroud)\n\n

但对称密钥每次都会改变,因此输出也每次都会改变。就像我说的,我尝试了不同的编码组合,但它们都返回类似的废话。正如 JS 代码所示,我已经加密了消息“test”。

\n\n

我以前从未实现过加密,所以我在这里可能离题很远,但是在盯着这段代码几天之后,任何见解都会受到赞赏。

\n\n

编辑:我在使用 PHP 中的私钥(而不是对称密钥)解密时遇到问题

\n

ljc*_*fty 5

弄清楚了!!!因此,我发现 PHP 有一个解密函数,无需使用名为openssl_private_decrypt的信封,该信封使用私钥来解密消息。通过使用该函数并对加密密钥进行 Base 64 解码,我能够在服务器端解密对称密钥,并且希望现在能够对称地解密消息。对于那些感兴趣的人,我在服务器端的代码是:

$key = openssl_get_privatekey( file_get_contents( $_SERVER['PRIV_KEY'] ) );
$encryptedKey = base64_decode(explode( ":::", $msg )[0]);

if( openssl_private_decrypt($encryptedKey, $decrypted, $key) )
{
    return $decrypted;
}
return $encryptedKey;
Run Code Online (Sandbox Code Playgroud)

在客户端,我的代码与上面的相同。希望这对某人有帮助!