sau*_*imo 3 encryption-asymmetric node.js node-crypto
我正在尝试实现基本的非对称加密;一个服务拥有公钥并使用该公钥加密一个值,然后另一个服务接收加密的消息,使用私钥对其进行解码,并对解密的数据执行某些操作。
\n我遇到的问题是,每次使用内置的crypto.publicEncrypt方法时,我都会返回不同的加密值。据我所知,我使用相同的输入,所以据我了解,我应该看到相同的输出。也许我误解了这一点?
\n这是我的加密实用程序;
\nimport { createPublicKey, createPrivateKey, privateDecrypt, publicEncrypt, constants } from "crypto";\n\nconst privateKeyPem = process.env.ENCRYPTION_PRIVATE_KEY;\nconst privateKeyPemFixed = privateKeyPem.replace(/\\\\n/g, "\\n");\nconst privateKey = createPrivateKey(privateKeyPemFixed);\nconst publicKey = createPublicKey(privateKey);\n\n// const private1 = privateKey.export({\n// type: \'pkcs1\',\n// format: \'pem\',\n// }).toString("base64");\n\n// const public1 = publicKey.export({\n// type: \'pkcs1\',\n// format: \'pem\',\n// }).toString("base64");\n\nexport const encrypt = (text: string): string => {\n const buffer = Buffer.from(text);\n\n const encrypted1 = publicEncrypt( {\n key: publicKey,\n oaepHash: \'sha256\',\n padding: constants.RSA_PKCS1_OAEP_PADDING,\n }, buffer);\n\n const encrypted2 = publicEncrypt({\n key: publicKey,\n oaepHash: \'sha256\',\n padding: constants.RSA_PKCS1_OAEP_PADDING,\n }, buffer);\n\n console.log(encrypted1.toString("base64"));\n console.log(encrypted2.toString("base64"));\n\n return encrypted1.toString("base64");\n}\n\nexport const decrypt = (cipher: string): string => {\n const buffer = Buffer.from(cipher);\n const decrypted = privateDecrypt(privateKey, buffer);\n return decrypted.toString("utf8");\n}\nRun Code Online (Sandbox Code Playgroud)\n我有一个笑话测试,如下所示;
\nimport { encrypt } from "./encryption";\n\ndescribe("encryption", () => {\n\n const helloWorld = "Hello world";\n const encryptedHelloWorld = "IIisobkVsZxKiR0e5nwyIHjsww/ebrKXI0hzDbdTdC8KMU2rc57IRX9krhVThVma2no7gZcMvbfwJsRjHz1s7NoBiT+BitgYlI/LE1jMpFd5Bmghy2S93F/wGFRWA4DMAqdw32I9s8CRKVvellxkh3ZlJ5NyzxWG8kVfc11CrEMD+1sqo2e9cFCcTdx5jEVYpCgITy7X2vDxUwOPQ7bK8K56kU5ivQhUfyoHjd9VclRUxfBaSzOwLJQqK6RJPbNwuUfILcCaR72GTf4zWMhQqIvs/zHhSu+S9QQYPVvmZ1SzqqJaCM9mM6Cvl8Gn2brwcMB003f0CFb8WFimOgM6lQ==";\n\n it("should encrypt text", () => {\n const received = encrypt(helloWorld);\n expect(received).toEqual(encryptedHelloWorld);\n });\n});\n\nRun Code Online (Sandbox Code Playgroud)\n然而它总是失败,因为结果似乎总是不同。
\n我在函数中运行了两次加密过程encrypt,以演示该问题;它注销的两个值完全不同,我不明白为什么。
console.log\n aDWDWcE+Zs92/rp2DLJN8UTgwHPTg6TDqFPIrC3ODVIfZgo5uaQV0NTSESPPPAGHhHeKiWB8JFnVewJaEN7iz9StzRepaL3+DFpD/CvhA8L7o8CQ5CTeScqL9HedVkM7O4MziMHkTJy0Li7EjP/6xdp8Caw+m6EsqvQ9Yd3qN4OTwrsMWmItLIaAHmkB/4UPhMqVnddVnwBUVb7toJ5rvGc/uktZkZPuHdzJRI0XSW//ltHHFCi3zneoJ92v/myYZOtWTyBDTmrgUtzC5fHbsSVdnD9IyWTRf72fz1Hjf2z8xFdFsdugo/+0qzOwE77K4BkgukeIDwhAxmdIr5yo4w==\n\n at encrypt (utils/encryption.ts:33:11)\n\n console.log\n LROC3KIjXJVoQVawJYZUYqT7rhXC8enb6O9ipY9VnOFMilFM00NHGiF3FHJQLWqac5zWFFZg2ofygANqT7Y5rQRtePcUEM5bLEUHvMaDdOAEXSdOK4PTbiCqZCAIPd79VVsW9gk2+vhKHbsq78AXhycCgUiOVjv25ooluDvqj3CQ+sTR+5cbatYO5kpXWwpu/BmPlRZYwsLUldpCuUPAYbkItKmQmiq/FWw1+z9Vx8mMKYhPtLuSTxnRrJ2Hn1eQm2EkuEeWQAEp+TJYaBsi93NalqmcWDo5swNe5HFPUH4hV7xtMtTZv82Wu9uNJ+ADUTD1B2mKDzKr0M0yNEYcGA==\n\n at encrypt (utils/encryption.ts:34:11)\nRun Code Online (Sandbox Code Playgroud)\n起初我想知道我的多行私钥是否有问题.env,但我可以导出我的私钥和公钥(请参阅注释掉的代码),当我注销它们时,它们看起来就像我所期望的那样,我认为这意味着正在keyObjects成功创建。如果密钥没有成功创建,也许每次都会创建新密钥,从而导致此失败?但据我所知,它们已成功创建。
我还阅读了这个答案,它表明 MacOS 上的 OpenSSL 实现可能存在问题 - 我使用的是 MacOs Big Sur,节点 14.16.0 (LTS)。所以,我brew install openssl然后链接它,现在我可以通过像这样检查来看到我正在使用 OpenSSL 而不是 LibreSSL;
console.log\n aDWDWcE+Zs92/rp2DLJN8UTgwHPTg6TDqFPIrC3ODVIfZgo5uaQV0NTSESPPPAGHhHeKiWB8JFnVewJaEN7iz9StzRepaL3+DFpD/CvhA8L7o8CQ5CTeScqL9HedVkM7O4MziMHkTJy0Li7EjP/6xdp8Caw+m6EsqvQ9Yd3qN4OTwrsMWmItLIaAHmkB/4UPhMqVnddVnwBUVb7toJ5rvGc/uktZkZPuHdzJRI0XSW//ltHHFCi3zneoJ92v/myYZOtWTyBDTmrgUtzC5fHbsSVdnD9IyWTRf72fz1Hjf2z8xFdFsdugo/+0qzOwE77K4BkgukeIDwhAxmdIr5yo4w==\n\n at encrypt (utils/encryption.ts:33:11)\n\n console.log\n LROC3KIjXJVoQVawJYZUYqT7rhXC8enb6O9ipY9VnOFMilFM00NHGiF3FHJQLWqac5zWFFZg2ofygANqT7Y5rQRtePcUEM5bLEUHvMaDdOAEXSdOK4PTbiCqZCAIPd79VVsW9gk2+vhKHbsq78AXhycCgUiOVjv25ooluDvqj3CQ+sTR+5cbatYO5kpXWwpu/BmPlRZYwsLUldpCuUPAYbkItKmQmiq/FWw1+z9Vx8mMKYhPtLuSTxnRrJ2Hn1eQm2EkuEeWQAEp+TJYaBsi93NalqmcWDo5swNe5HFPUH4hV7xtMtTZv82Wu9uNJ+ADUTD1B2mKDzKr0M0yNEYcGA==\n\n at encrypt (utils/encryption.ts:34:11)\nRun Code Online (Sandbox Code Playgroud)\n然而,这似乎并没有产生什么影响。
\n那么,在给定相同的输入的情况下,我该怎么做才能使加密函数可靠地返回相同的输出呢?
\n编辑
\n我已将加密实用程序更新为以下内容,并接受加密结果会有所不同,因为它是使用唯一的会话密钥和公钥进行加密的,但是所有输出值都使用私钥正确解密。
\n\xe2\x9e\x9c website git:(master) \xe2\x9c\x97 openssl version\nOpenSSL 1.1.1j 16 Feb 2021\nRun Code Online (Sandbox Code Playgroud)\n
事实证明我的假设crypto.PublicEncrypt是错误的。引用这个答案
纯函数标准 1:使用相同值调用函数必须始终产生相同的返回值
在进行非对称加密时这是不可能的,因为每次操作都会生成随机会话密钥。使用公钥对会话密钥进行加密,然后使用会话密钥对有效负载进行加密。返回的值通常只是两个值的编码版本:(1) pubkey 加密的会话密钥,以及 (2) 会话密钥加密的有效负载。
每次调用该函数时,这两个值都会不同,因为会话密钥每次都会不同。
然而,尽管返回值比较不相等,但我认为它们在语义上是相等的——也就是说,如果您使用匹配的私钥解密每个值,则解密的值将比较相等。
所以我将测试更新为;
import { decrypt, encrypt } from "./encryption";
describe("encryption", () => {
it("should encrypt and decrypt text", () => {
const encrypted = encrypt("Hello World");
const decrypted = decrypt(encrypted);
expect(decrypted).toEqual("Hello World");
});
});
Run Code Online (Sandbox Code Playgroud)
现在它正在发挥作用。