【发布时间】:2022-01-21 07:15:54
【问题描述】:
我目前在 PHP 中加密数据如下:
//$sMessage is the input to encrypt.
//$sPublicKey is the public key in PEM format.
openssl_public_encrypt($sMessage, $sEncrypted, $PublicKey, OPENSSL_PKCS1_OAEP_PADDING);
//$sEncrypted will now store the resulting text.
以下是 PHP 中用于生成密钥的代码示例:
$aConfig = array(
"digest_alg" => "sha256",
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
);
$res = openssl_pkey_new($aConfig);
//$sPassPhrase is the pass phrase.
openssl_pkey_export($res, $sPrivateKey, $sPassPhrase);
//$sPrivateKey is the key (in PEM format).
我的解密是使用受密码保护的私钥。
//$sPrivateKeyWithPassPhrase is the protected private key in PEM format.
//$sPassPhrase is the pass phrase to protect the key.
$newRes = openssl_pkey_get_private($sPrivateKeyWithPassPhrase, $sPassPhrase);
//$sEncrypted is the encrypted text (ciphertext).
openssl_private_decrypt($sEncrypted, $sDecrypted, $newRes, OPENSSL_PKCS1_OAEP_PADDING);
//$sDecrypted is the decrypted text (plaintext)
我还发现了如何使用密码库 (which you can learn about here) 使用 Python 进行解密:
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
#passphrase is the pass phrase
passphrase_bytes = bytes(passphrase, 'utf-8')
#privatekey is the encrypted private key
private_key = serialization.load_pem_private_key(
privatekey,
password=passphrase_bytes,
)
#ciphertext is the text to be decrypted
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
#plaintext will be the decrypted result.
但是,我一直在努力在 JavaScript 中找到类似的函数。
目前我找到的最佳答案是这个:RSA Encryption Javascript
但是,密钥似乎不是 PEM 格式,当我去 pidCrypt 主页获取更多文档时,这是一个 404 错误。
我也找到了这个:PHP's openssl_sign Equivalent in Node JS
总的来说,NodeJS 库似乎具有正确的功能,但是当我浏览 NodeJS 文档时,Quick Start Guide 似乎暗示要使用 NodeJS,我必须首先安装软件并设置 Web 服务器。根据how to run node.js client on browser,不可能“Node.js 不是浏览器 javascript。它的许多部分使用浏览器上下文中不可用的操作系统功能。” (我希望我可以在客户端的本机浏览器中运行一些东西。)
有人在评论中建议我可以使用 WebCrypto。经过一番努力弄清楚在哪里下载它,我发现它实际上是浏览器的原生(这是一个惊喜)。但是,我无法弄清楚如何从文档中导入 PEM 密钥,当我生成密钥然后导出它时,唯一可用的格式是“jwk”(某种 JavaScript 对象),“ spki”(某种数组缓冲区)和“pkcs8”(我只得到 DOMException: key is not extractable)。没有什么看起来像 OpenSSL PEM 格式。 (我相信这是 PKCS1。)
当我执行“crypto.subtle.importKey”时,它需要 5 个不同的参数(格式、keyData、算法、可提取、keyUsages)。这些都不接受 PEM 字符串。经过一番挣扎,我确实找到了SubtleCrypto importKey from PEM,它确认如果您进行花哨的操作来导入 PEM 公钥,这是可能的,但是这是针对 PEM 格式的公钥,我不知道如何处理密码短语(实际上我'宁愿不要手动编程)。然后我找到了How can I import an RSA private key in PEM format for use with WebCrypto? 和Javascript, crypto.subtle : how to import RSA private key? 但是那些基本上告诉我这是不可能的,除非我去使用命令行 OpenSSL 将私钥转换为 PKCS8(这也必须单独安装,我记得这是一个巨大的痛苦在 Windows 上)。一旦我克服了这个障碍,我仍然不确定如何在 PKCS8 中获得等效的密码保护。我希望有类似的东西可以理想地支持 PKCS1 来执行与上面的 PHP 和 Python 代码相同的操作,并且我可以在本机浏览器中 100% 运行它。 (导入更多的 JavaScript 代码是可以的。)
理想情况下,我希望找到一个简单的用于 OpenSSL RSA 解密的 JavaScript 示例,相当于上面的 PHP 或 Python 示例。如果我有私钥 PEM 字符串、密码短语和密文,它可以返回明文。
非常感谢!非常感谢您的所有帮助,您可以为我节省很多时间!
【问题讨论】:
-
如何将我的私钥(PEM 格式,它是一个字符串)加载到这些系统之一?当我在那里生成密钥时,似乎无论我指定什么,导出都是一个有趣的复杂对象,看起来不像 OpenSSL PEM 格式,我不知道如何使用它。我将编辑问题以澄清我不是在寻找库建议,而是在任何维护的库中与 PHP 或 Python 等效的工作示例。
-
好的,我又花了一个小时试图让 NodeJS 或 WebCrypto 工作,并将我的具体问题添加到问题中。同样,我对任何与 PHP 或 Python 示例相同的有效 JavaScript 示例感到满意。
-
NodeJS 看起来完全有我需要的功能,但是我不知道如何在浏览器中运行它。根据stackoverflow.com/questions/28059521/…,不可能“Node.js 不是浏览器 javascript。它的许多部分使用浏览器上下文中不可用的操作系统功能。”明确地说,当我说 JavaScript 时,我的意思是能够在浏览器中解密,这样我就可以拥有一个包含一些 JavaScript 的 HTML 文件,而无需安装任何自定义软件。
-
至于 SubtleCrypto,我相信我最终可以弄清楚如何手动解密它。令我惊讶的是,没有一个简单的标准库或函数可以为我做到这一点。我认为找到一个(如果存在的话)会更快,但我还没有遇到过。为什么它不向后兼容 PKCS1?必须有一个更好的解决方案,我错过了。
-
我知道,在幕后,这些算法有很多复杂性,而且我知道构建和测试框架需要时间,而且许多密码学家在使事情变得简单或易于使用时遇到了麻烦.但我认为,每当出现隐私泄露或某人的数据被泄露或主要组织滥用人们的个人信息时,它可能会成为帮助使密码学更易于访问的一些动力,以便更多的项目和个人能够更好地理解和正确保护他们的信息.
标签: javascript encryption openssl rsa sha1