Javascript nodejs加密模块privateEncrypt()始终返回相同的结果

Javascript nodejs加密模块privateEncrypt()始终返回相同的结果,javascript,node.js,encryption,rsa,cryptojs,Javascript,Node.js,Encryption,Rsa,Cryptojs,我正在使用RSA加密和nodejs加密模块 我想用私钥加密消息,用公钥解密。 同样,总是使用填充方案对同一消息产生不同的结果,就像使用公钥加密一样 所以我使用了下面这样的基本加密模块 var crypto = require('crypto'); var fs = require('fs'); const path = require('path'); var PRIVKEY = fs.readFileSync(path.join(__dirname, 'private.key'), 'ut

我正在使用RSA加密和nodejs加密模块

我想用私钥加密消息,用公钥解密。 同样,总是使用填充方案对同一消息产生不同的结果,就像使用公钥加密一样

所以我使用了下面这样的基本加密模块

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
公共加密->PRVATE解密操作良好,如我所料。由于填充方案的原因,它总是返回不同的结果

但私有加密->公共解密总是返回相同的消息,尽管使用了填充方案


是否有任何解决方案使其与Nodejs加密模块的消息不同?

根据OpenSSL实现的RSA签名和加密填充方案,这是预期的行为

我不确定您想使用这些函数和用于什么。如果您的目的是签署数据,请参阅下面的“我的更新”。无论如何,对于这些函数,
crypto
文档解释说,它只公开了
RSA_PKCS1_PADDING
,OpenSSL将其映射到引擎盖下的确定性RSASSA-PKCS1-v1_5 PADDING方案。这意味着对于相同的键和相同的数据,结果数据将是相同的

对于加密和解密,使用和,您选择了
RSA\u PKCS1\u PADDING
模式。这转化为RSAES-PKCS1-v1_5,这是一个包含随机元素的方案,它会导致您在重复运行中观察到不同的输出。根据文档,默认情况下,
crypto
使用
RSA\u PKCS1\u OAEP\u填充。这代表,这也是不确定的

有关PKCS#1定义方案的摘要,请参阅


更新:您可能希望使用而不是
privateEncrypt()
publicDecrypt()
函数。它的功能确实支持概率填充模式,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')
每次签名都不一样。请注意,您不能“解密”它,这是一个单向操作。您只能在类中使用公钥对其进行验证:


您需要@kelalaka RSA-OAEP用于加密和解密,并且实际支持,
crypto
的默认值。“问题”在于签名,而需要的是。看,是的,如果我们把私有加密称为签名。签名!=私有加密。@kelalaka我更新了我的答案,并解释了签名(与私有加密相反)。这应该更清楚。关于您的评论,我想知道是否有理由将
privateEncrypt()
用于签名以外的其他目的。@kelalaka谢谢,有趣的阅读。一些实施者加剧了这一问题。例如,您提到的
RSA\u sign
函数:-)@cockroach54我的荣幸,您的问题提出得很好,欢迎使用StackOverflow.Um。。我可以再问你一个问题吗???我计划在客户端应用程序中嵌入公钥,在管理应用程序中嵌入私钥。管理员应用程序用户加密某种代码(加密的代码必须是不同的随机)并将其交给客户端应用程序。客户端只对代码进行解密,但不应该知道如何对其进行加密。在这种情况下,若管理员使用公钥,而客户端使用私钥,则客户端可以使用私钥生成公钥。这是一个问题。我可以自定义privateEncrypt()使用RSASSA-PKCS1-v1_5-->RSAES-PKCS1-v1_5???@cockroach54这太大了,无法在评论中回复,请将其作为新问题提交以获得正确答案。。。
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'))