Я пытаюсь реализовать базовое асимметричное шифрование; одна служба имеет открытый ключ и шифрует значение с помощью этого открытого ключа, а затем другая служба получает зашифрованное сообщение, декодирует его с помощью закрытого ключа и что-то делает с расшифрованными данными.
Проблема, с которой я сталкиваюсь, заключается в том, что каждый раз, когда я использую встроенный crypto.publicEncrypt, я получаю другое зашифрованное значение. Насколько я могу судить, я использую одни и те же входные данные, поэтому, насколько я понимаю, я должен видеть тот же результат. Может, я неправильно это понял?
Вот моя утилита шифрования;
import { createPublicKey, createPrivateKey, privateDecrypt, publicEncrypt, constants } from "crypto";
const privateKeyPem = process.env.ENCRYPTION_PRIVATE_KEY;
const privateKeyPemFixed = privateKeyPem.replace(/\\n/g, "\n");
const privateKey = createPrivateKey(privateKeyPemFixed);
const publicKey = createPublicKey(privateKey);
// const private1 = privateKey.export({
// type: 'pkcs1',
// format: 'pem',
// }).toString("base64");
// const public1 = publicKey.export({
// type: 'pkcs1',
// format: 'pem',
// }).toString("base64");
export const encrypt = (text: string): string => {
const buffer = Buffer.from(text);
const encrypted1 = publicEncrypt( {
key: publicKey,
oaepHash: 'sha256',
padding: constants.RSA_PKCS1_OAEP_PADDING,
}, buffer);
const encrypted2 = publicEncrypt({
key: publicKey,
oaepHash: 'sha256',
padding: constants.RSA_PKCS1_OAEP_PADDING,
}, buffer);
console.log(encrypted1.toString("base64"));
console.log(encrypted2.toString("base64"));
return encrypted1.toString("base64");
}
export const decrypt = (cipher: string): string => {
const buffer = Buffer.from(cipher);
const decrypted = privateDecrypt(privateKey, buffer);
return decrypted.toString("utf8");
}
У меня есть тест-шутка, который выглядит так:
import { encrypt } from "./encryption";
describe("encryption", () => {
const helloWorld = "Hello world";
const encryptedHelloWorld = "IIisobkVsZxKiR0e5nwyIHjsww/ebrKXI0hzDbdTdC8KMU2rc57IRX9krhVThVma2no7gZcMvbfwJsRjHz1s7NoBiT+BitgYlI/LE1jMpFd5Bmghy2S93F/wGFRWA4DMAqdw32I9s8CRKVvellxkh3ZlJ5NyzxWG8kVfc11CrEMD+1sqo2e9cFCcTdx5jEVYpCgITy7X2vDxUwOPQ7bK8K56kU5ivQhUfyoHjd9VclRUxfBaSzOwLJQqK6RJPbNwuUfILcCaR72GTf4zWMhQqIvs/zHhSu+S9QQYPVvmZ1SzqqJaCM9mM6Cvl8Gn2brwcMB003f0CFb8WFimOgM6lQ==";
it("should encrypt text", () => {
const received = encrypt(helloWorld);
expect(received).toEqual(encryptedHelloWorld);
});
});
Однако он постоянно терпит неудачу, так как результат всегда кажется другим.
Я дважды запускал процесс шифрования в функции encrypt
, чтобы продемонстрировать проблему; два значения, которые он выводит из системы, совершенно разные, и я не понимаю, почему.
console.log
aDWDWcE+Zs92/rp2DLJN8UTgwHPTg6TDqFPIrC3ODVIfZgo5uaQV0NTSESPPPAGHhHeKiWB8JFnVewJaEN7iz9StzRepaL3+DFpD/CvhA8L7o8CQ5CTeScqL9HedVkM7O4MziMHkTJy0Li7EjP/6xdp8Caw+m6EsqvQ9Yd3qN4OTwrsMWmItLIaAHmkB/4UPhMqVnddVnwBUVb7toJ5rvGc/uktZkZPuHdzJRI0XSW//ltHHFCi3zneoJ92v/myYZOtWTyBDTmrgUtzC5fHbsSVdnD9IyWTRf72fz1Hjf2z8xFdFsdugo/+0qzOwE77K4BkgukeIDwhAxmdIr5yo4w==
at encrypt (utils/encryption.ts:33:11)
console.log
LROC3KIjXJVoQVawJYZUYqT7rhXC8enb6O9ipY9VnOFMilFM00NHGiF3FHJQLWqac5zWFFZg2ofygANqT7Y5rQRtePcUEM5bLEUHvMaDdOAEXSdOK4PTbiCqZCAIPd79VVsW9gk2+vhKHbsq78AXhycCgUiOVjv25ooluDvqj3CQ+sTR+5cbatYO5kpXWwpu/BmPlRZYwsLUldpCuUPAYbkItKmQmiq/FWw1+z9Vx8mMKYhPtLuSTxnRrJ2Hn1eQm2EkuEeWQAEp+TJYaBsi93NalqmcWDo5swNe5HFPUH4hV7xtMtTZv82Wu9uNJ+ADUTD1B2mKDzKr0M0yNEYcGA==
at encrypt (utils/encryption.ts:34:11)
Сначала я подумал, есть ли проблема с моим многострочным закрытым ключом в моем .env
, но я могу экспортировать свои закрытый и открытый ключи (см. Закомментированный код), и когда я выхожу из системы, они выглядят так, как я ожидал, что, как мне кажется означает, что keyObjects
успешно создаются. Если ключи не были созданы успешно, возможно, он будет создавать новые ключи каждый раз, и это вызовет этот сбой? Но насколько я могу судить, они успешно создаются.
Я также прочитал этот ответ, в котором говорилось, что может быть проблема с реализацией OpenSSL на MacOS - я использую MacOs Big Sur, узел 14.16.0 (LTS). Итак, я brew install openssl
, а затем связал его, и теперь я вижу, что использую OpenSSL, а не LibreSSL, проверяя так;
➜ website git:(master) ✗ openssl version
OpenSSL 1.1.1j 16 Feb 2021
Однако это, похоже, не имело значения.
Итак, что я могу сделать, чтобы функция шифрования надежно возвращала тот же вывод при том же вводе?
ИЗМЕНИТЬ
Я обновил свою утилиту шифрования следующим образом и согласен с тем, что результат шифрования будет другим, потому что он зашифрован с помощью уникального сеансового ключа, а также открытого ключа, однако все выходные значения правильно расшифровываются с помощью закрытого ключа.
import { createPublicKey, createPrivateKey, privateDecrypt, publicEncrypt } from "crypto";
const privateKeyPem = process.env.ENCRYPTION_PRIVATE_KEY;
const privateKeyPemFixed = privateKeyPem.replace(/\\n/g, "\n");
const privateKey = createPrivateKey(privateKeyPemFixed);
const publicKey = createPublicKey(privateKey);
export const encrypt = (text: string): string => {
const buffer = Buffer.from(text, "utf8");
const encrypted = publicEncrypt(publicKey, buffer);
return encrypted.toString("base64");
}
export const decrypt = (cipher: string): string => {
const buffer = Buffer.from(cipher, "base64");
const decrypted = privateDecrypt(privateKey, buffer);
return decrypted.toString("utf8");
}