криптомодуль nodejs privateEncrypt () всегда возвращает один и тот же результат - PullRequest
0 голосов
/ 15 января 2019

Я использую шифрование RSA с криптомодулем nodejs.

Я хочу зашифровать сообщение с помощью PRIVATE KEY и расшифровать с помощью PUBLIC KEY. также всегда дают разные результаты с одним и тем же сообщением, используя схему заполнения, такую ​​как шифрование с использованием открытого ключа.

Итак, я использовал базовый криптомодуль, как показано ниже

var crypto = require('crypto');
var fs = require('fs');
const path = require('path');


var PRIVKEY = fs.readFileSync(path.join(__dirname, 'private.key'), 'utf8');
var PUBKEY = fs.readFileSync(path.join(__dirname, 'pub.key'), 'utf8');

// RSA PRIVATE ENCRYPT -> PUBLIC DECRYPT //
myMSG = "apple";
console.log('myMSG SIZE:', myMSG.length);

function privENC_pubDEC(originMSG){
 encmsg = crypto.privateEncrypt(PRIVKEY, Buffer.from(originMSG, 'utf8') ).toString('base64');
 msg = crypto.publicDecrypt(PUBKEY, Buffer.from(encmsg, 'base64'));
 console.log("Encrypted with private key : "+encmsg);
 console.log(msg.toString());
}

// RSA PUBLIC ENCRYPT -> PRVATE DECRYPT //
function pubENC_privDEC(originMSG){
 encmsg = crypto.publicEncrypt({key:PUBKEY, padding:crypto.constants.RSA_PKCS1_PADDING}, Buffer.from(originMSG, 'utf8') ).toString('base64');
 msg = crypto.privateDecrypt({key:PRIVKEY, padding:crypto.constants.RSA_PKCS1_PADDING}, Buffer.from(encmsg, 'base64'));
 console.log("\nEncrypted with public key : "+encmsg);
 console.log(msg.toString());
}

privENC_pubDEC(myMSG);
pubENC_privDEC(myMSG);

Результат

C:\Users\LSW>node crypto.js
myMSG SIZE: 5
Encrypted with private key : fbUZwj+UZP92HQYRc+EJTqSztJTY/Sit5axPZ0NVBuDAC8ZwvvC96pxxDGpra4Yg8MjcXyjvnT8rrrgHu0T0wA==
apple

Encrypted with public key : ze+5TdWtR8hkpNPIVa5HSasOxs3Pr8FA/1/zUGqDUQmIhs/miWt5pgU9kIAiryKfgGa0+p9RfHPMwZ1VMSA7Bw==
apple

C:\Users\LSW>node crypto.js
myMSG SIZE: 5
Encrypted with private key : fbUZwj+UZP92HQYRc+EJTqSztJTY/Sit5axPZ0NVBuDAC8ZwvvC96pxxDGpra4Yg8MjcXyjvnT8rrrgHu0T0wA==
apple

Encrypted with public key : OdEpjloUDWI8+YjWkE5cmBC/fJL2QnRLKBXfjaP5h5qyB1OMcm9JGGNSTiAAL2u8O5jjdQAavB9Rn+cdRDjLyA==
apple

C:\Users\LSW>node crypto.js
myMSG SIZE: 5
Encrypted with private key : fbUZwj+UZP92HQYRc+EJTqSztJTY/Sit5axPZ0NVBuDAC8ZwvvC96pxxDGpra4Yg8MjcXyjvnT8rrrgHu0T0wA==
apple

Encrypted with public key : INspxkyFu2AWGVYwSvOGOPH1fhE3qVVxiqz+SmyHU8wTDNKHj4gVVHqO+8AZOJvi4NfyekI2MMwpFDU4mUjEXA==
apple

PUBLIC ENCRYPT -> PRVATE DECRYPT работает хорошо, как я и ожидал. он всегда возвращает другой результат из-за схемы заполнения.

Но PRIVATE ENCRYPT -> PUBLIC DECRYPT всегда возвращает одно и то же сообщение, хотя используется схема заполнения.

Есть ли какое-нибудь решение сделать это другим сообщением с криптомодулем Nodejs ???

1 Ответ

0 голосов
/ 15 января 2019

Это ожидаемое поведение в соответствии со схемами заполнения для подписи и шифрования RSA, реализованными OpenSSL, , которые crypto используют .

Я не уверен, для чего вы хотите использовать функции privateEncrypt() и publicDecrypt(). Если вы намереваетесь подписать данные, см. Мое обновление ниже. В любом случае, для этих функций документация crypto объясняет, что она только раскрывает RSA_PKCS1_PADDING, который OpenSSL отображает на детерминированную схему заполнения RSASSA-PKCS1-v1_5 под капотом. Это означает, что для одного и того же ключа и одних и тех же данных результирующие данные будут одинаковыми.

Для шифрования и дешифрования, с помощью publicEncrypt() и privateDecrypt(), вы выбрали режим RSA_PKCS1_PADDING. Это преобразуется в RSAES-PKCS1-v1_5, схему, которая включает в себя случайные элементы, которые вызывают различные выходные данные, которые вы наблюдаете в ваших повторных прогонах. Согласно документации, crypto использует заполнение RSA_PKCS1_OAEP_PADDING по умолчанию. Это означает Оптимальное асимметричное заполнение шифрования , которое также является недетерминированным.

Сводка схем, определенных PKCS # 1, приведена в Схемы PKCS # 1 .


Обновление: вы можете использовать Sign class вместо функций privateEncrypt() и publicDecrypt(). Его функция sign () поддерживает вероятностный режим заполнения, который OpenSSL поддерживает через RSASSA-PSS. Используя ваш пример кода в качестве отправной точки, он будет выглядеть примерно так:

const sign = crypto.createSign('SHA256')
sign.update(Buffer.from(originMSG, 'utf8'))
signature = sign.sign({key:PRIVKEY, padding:crypto.constants.RSA_PKCS1_PSS_PADDING}).toString('base64')

Подпись будет отличаться каждый раз. Обратите внимание, что вы не можете «расшифровать» его, это односторонняя операция. Вы можете проверить это только с помощью открытого ключа с классом Verify:

const verify = crypto.createVerify('SHA256')
verify.update(Buffer.from(originMSG, 'utf8'))
verifyRes = verify.verify({key:PUBKEY, padding:crypto.constants.RSA_PKCS1_PSS_PADDING}, Buffer.from(signature, 'base64'))
...