非对称加密,一般由发送方(客户端)和接收方(服务端)各持有一对公钥和私钥。
私钥可以推出公钥,公钥不能推出私钥。
数据交换的过程中,双方交换自己的公钥。各自私钥不公开。
发送时使用对方的公钥进行加密。接收对方发来的密文时,使用自己私钥进行解密。
发送方使用私钥将信息进行加签(签名),将密文与签名作为参数发起请求。
接收方用自己私钥解密得到的明文,请求方公钥,接收的签名,进行验签(签名验证)。
为了增强数据交换的安全性。
假设不进行签名和验签:
发送方如果增加签名可以不用加密请求参数,但第三方拦截后能看到请求参数的明文(参数格式和内容被公开)。
安全性的前提是私钥没有泄露,私钥若被攻击者获取了,那么签名也可以伪造了。
const NodeRSA= require('node-rsa');
const publicKey =`
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAISIIx8u/n7M6GyGoXIotkDZKfDk28JJ
3jDhhhFm2i8+2h5NJqmgYIZIsGR4TdeD/Uti0UYFfpdVAsK4/fgyGqsCAwEAAQ==
-----END PUBLIC KEY-----
`;
const privateKey = `
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAISIIx8u/n7M6GyGoXIotkDZKfDk28JJ3jDhhhFm2i8+2h5NJqmg
YIZIsGR4TdeD/Uti0UYFfpdVAsK4/fgyGqsCAwEAAQJAHtZSXcIggz6IYiAdVqO0
bHhbMur9W0K2yWbgPBJTeCRxAdsx2ZJK45WfgOn+vCuuXQKNrADk84eCGyg/32AB
0QIhALlhkxdzAvUg4Q1gzn6n6nRI3C2jFPB6XOd64DMv05KpAiEAtwStPQPP5Kyx
3yxmPlprPeOJZdSfYs9RJ/pdQ/+NqzMCIQCCYYL/cg95chd2vkhdQiIeiQP6QQHA
JH9k+sHmnlOSiQIgHn1S9wU5jxkOEOXuqpiZoRfU/ffsDaQIGybkfr2GNm0CIQCK
TUs08mJG+BUvmyYe6YgY5MHuNoKx4ewXh/P0uaxPHw==
-----END RSA PRIVATE KEY-----
`;
const key = new NodeRSA({b:512});//传入{b:512} 生成512位秘钥。也可以指定publicKey /privateKey 字符串
// 加密
let encrypted = key.encrypt('你的行为和表现还是让我无法完全相信你放下了','base64');
console.log(encrypted); // VtBuzrpbcxg/F6UNYwIeN6iAwGEFabwvxGypQ3zvoH+6xJjNdnIllOf7BDpgPtNfhAQpiynwWdYEpc7ncOV4zU6/UOnNsArKITbfwYm3x42rqC0RgTtvrRSy5LAEPPjbYDgCZVqMF2vBJJTHdZkGQr6hmLsL4lMVOCunaoiLhPckNo5fih94WK/31FzpgSR5Bzrh02w4P7EQAt9+5MyDucjFLcb9VQLsfdXQtyiS+2CSVpVbVK7OnSaQ4GiK+uV9
// 解密
let decrypted = key.decrypt(encrypted,'utf8');
console.log(decrypted);
rsa私钥可以推出公钥,公钥不能推出私钥。
console.log(new NodeRSA(privateKey).exportKey('public'));
console.log(new NodeRSA(publicKey).exportKey('private')); // 报错 not privateKey
let message = '你的行为和表现还是让我无法完全相信你放下了';
// 服务端公钥加密
let encryptedText = new NodeRSA(publicKey).encrypt(message, 'base64');
console.log('密文:', encryptedText);
// 使用客户端私钥加签
let signature = new NodeRSA(privateKey).sign(Buffer.from(message), 'hex');
console.log('签名:', signature);
// 服务端接收的密文
let encryptedText = 'H1WkC6vd2+mNe0RyDXwJex4urWHyWTg4QFJoDWF9uqiWCoUNdLE1MGNaWYsPzSd7bMnq2McwRFKImvvX49l8MWn8psd0BztrMkRZYYNAkHaKUZ/VMEn+d0h7k1nKPS8k36KZmOhwoOubzMjdN84TUVzOIjs59gJ99xJa9T0pGsNtiK2XJ/+XsUjnE37ZQo7NwOlZieZKXn4Muflm2pTrLMa17XqJhIvFgJm0iRX/aiUuDDL+g0og/a21Yl/T3qAr';
// 服务端私钥解密
let decryptedText = new NodeRSA(privateKey).decrypt(encryptedText, 'utf8');
console.log('解密:', decryptedText);
// 客户端公钥验签
let verify = new NodeRSA(publicKey).verify(Buffer.from(decryptedText), signature, 'utf-8', 'hex');
console.log('验证签名', verify);