Skip to content

Commit

Permalink
add: rsa javascript encryption and decryption algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
TRHX committed Mar 19, 2024
1 parent 44e29be commit 3f39a19
Showing 1 changed file with 193 additions and 7 deletions.
200 changes: 193 additions & 7 deletions docs/03.辅助查询/04.加密算法/07.rsa.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ article: false
::: details 关于 RSA 非对称加密算法
RSA 加密算法是一种非对称加密算法,是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在 1977 年一起提出的,RSA 就是他们三人姓氏开头字母拼在一起组成的。RSA 公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

<!--填充方式(padding):
- `RSA_PKCS1_PADDING`: 使用 PKCS #1 v1.5 填充方案;
- `RSA_PKCS1_OAEP_PADDING`: 使用 OAEP 填充方案;
- `RSA_NO_PADDING`: 不使用填充方案。需要手动处理输入数据的长度;
- `RSA_PKCS1_PSS_PADDING`: 使用 PSS (Probabilistic Signature Scheme) 填充方案。
-->

::: right
RSA [维基百科](https://en.wikipedia.org/wiki/RSA_(cryptosystem))
:::
Expand Down Expand Up @@ -1602,6 +1595,27 @@ nHPppz1nsV+COkxXQV4=
```

## 加密解密

::: details 关于加密解密
在 RSA 加密解密操作中,我们需要注意的是填充方式(padding),最常见的分为以下四种:

- `RSA_NO_PADDING`: 不使用填充方案;
- `RSA_PKCS1_PADDING`: 最常见,使用 PKCS#1 v1.5 填充方案;
- `RSA_PKCS1_OAEP_PADDING`: OAEP (Optimal asymmetric encryption padding),最优非对称加密填充,在 PKCS#1 v2 中标准化;
- `RSA_PKCS1_PSS_PADDING`: PSS (Probabilistic signature scheme),概率签名方案,在 PKCS#1 v2.1 中标准化。

---

::: right
【实用参考资料】

Padding 维基百科:[https://en.wikipedia.org/wiki/Padding_(cryptography)](https://en.wikipedia.org/wiki/Padding_(cryptography))<br/>
RSA Padding 维基百科:[https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Padding](https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Padding)<br/>
聊聊密码学中的Padding:[https://cloud.tencent.com/developer/article/1499219](https://cloud.tencent.com/developer/article/1499219)<br/>
PSS (Probabilistic signature scheme):[https://en.wikipedia.org/wiki/Probabilistic_signature_scheme](https://en.wikipedia.org/wiki/Probabilistic_signature_scheme)<br/>
OAEP (Optimal asymmetric encryption padding):[https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding](https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding)
:::

### Python <Badge text="3.0+"/>
<br/>

Expand All @@ -1618,9 +1632,181 @@ nHPppz1nsV+COkxXQV4=

<code-group>
<code-block title="加密解密 1️⃣" active>
```javascript
// ✅ Node.js 内置 crypto 模块,无需单独安装,官方文档:https://nodejs.org/docs/latest/api/crypto.html

var crypto = require("crypto");


function rsaEncrypt(data) {
var bufferData = Buffer.from(data);
var encrypted = crypto.publicEncrypt({
key: publicKey,
// 支持 RSA_NO_PADDING、RSA_PKCS1_PADDING、RSA_PKCS1_OAEP_PADDING、RSA_PKCS1_PSS_PADDING
padding: crypto.constants.RSA_PKCS1_PADDING
}, bufferData);
return encrypted.toString("base64");
}

function rsaDecrypt(cipherText) {
var bufferData = Buffer.from(cipherText, "base64");
var decrypted = crypto.privateDecrypt({
key: privateKey,
// 支持 RSA_NO_PADDING、RSA_PKCS1_PADDING、RSA_PKCS1_OAEP_PADDING、RSA_PKCS1_PSS_PADDING
padding: crypto.constants.RSA_PKCS1_PADDING
}, bufferData);
return decrypted.toString();
}

// pkcs1 标准 pem 格式的公钥
var publicKeyPkcs1Pem = `
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALLA/aUElSxqvPUnlC4A8UaNh6txyrjlLshW4/wUgWZIBBbvp7yVj4Oi
C5mbbbyvOqElQNhkaeV8EF2rZqy9m5whs+jIx1tUdyJPJXLyZCNr3Q8t4sQyek6q
1+imN6KUEIHrLveuYq1Lvmw3lt52vRzvWwucYV0EHSbx3G0b6hErAgMBAAE=
-----END RSA PUBLIC KEY-----
`

// pkcs1 标准 pem 格式的私钥
var privateKeyPkcs1Pem = `
-----BEGIN RSA PRIVATE KEY-----
MIICYAIBAAKBgQCywP2lBJUsarz1J5QuAPFGjYerccq45S7IVuP8FIFmSAQW76e8
lY+DoguZm228rzqhJUDYZGnlfBBdq2asvZucIbPoyMdbVHciTyVy8mQja90PLeLE
MnpOqtfopjeilBCB6y73rmKtS75sN5bedr0c71sLnGFdBB0m8dxtG+oRKwIDAQAB
AoGADOrlaYdrQEp2XUD+9FQdG3we0cTnYXUubEvbLdxNfZa2tPGcrYQhWuHa9L7G
r1v6YKrQhNK81Fii1iIMvBnzkVIakhSYvC294yyEZG+fYJcXuZWzoF0+YUrlFP0b
vG5JOpDcUN4YG+tG924AbhyPL0AJkX0BEElSWaFhVtnTxAECRQC4fMLIzE2hCq9F
UmR59YDSHasPUVDWuq0eXG+P/0Kp9x5ZUDjZcojcBhpsJBQbx9P4ygyiYj4uUw3O
SA8X/fZHxqmg/QI9APgLR5Uz5Veaj1PguhkoKB3384PnrrKoFD+wgc6H7Qib9aKG
KT0x5dKswZefyE/PF+Qi7hMWiO18FK2HRwJEb/eQREvyhV21uE3kGzzL3ToSWq6Q
cHJFpVqWfv9+Fyea7LvKdPaVZ2vw11ciOSYTWThPaLJVaMoRY/PJ7Va+BRvmUYUC
PQCO06fnYReZRxVq3gcqvzXCc+kTtg+hLilitxc3vosdnvhlGk2awCWvFuzuiwID
+qKuKfLeqOY1oXIirbcCRGtG4PspKLAQMO6jI7bFUc5if9UKo6TGeu39E3qtv4jW
NW6qObPBJ9R1gurMqPUT9g630xjZdZxz6ac9Z7FfgjpMV0Fe
-----END RSA PRIVATE KEY-----
`

// 将 pem 格式的密钥转换为 crypto 可以使用的对象
var publicKey = crypto.createPublicKey(publicKeyPkcs1Pem);
var privateKey = crypto.createPrivateKey(privateKeyPkcs1Pem);

// RSA 加解密,填充方式使用 RSA_PKCS1_PADDING,其他可选 RSA_NO_PADDING、RSA_PKCS1_OAEP_PADDING、RSA_PKCS1_PSS_PADDING
var data = "spiderapi.cn - 虫术";
var resultEncrypted = rsaEncrypt(data);
var resultDecrypted = rsaDecrypt(resultEncrypted);

console.log("RSA PKCS1Padding 加密结果: ", resultEncrypted)
console.log("RSA PKCS1Padding 解密结果: ", resultDecrypted)

```
</code-block>

<code-block title="加密解密 2️⃣">
```javascript
// ✅ 安装依赖:npm install node-rsa,官方文档:https://github.com/rzcoder/node-rsa
// ❓ 注意:截止 2024.03,该库中公钥语法标准支持 pkcs8,但实际上不存在这种说法,具有争议,正确应该是 spki,参见:https://github.com/rzcoder/node-rsa/issues/208
// ❌ padding 填充方式只支持 PKCS1、PKCS1_OAEP,不支持 NO_PADDING、PKCS1_PSS
var NodeRSA = require("node-rsa");
// pkcs1 标准 pem 格式的公钥
var publicKeyPkcs1Pem = `
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALLA/aUElSxqvPUnlC4A8UaNh6txyrjlLshW4/wUgWZIBBbvp7yVj4Oi
C5mbbbyvOqElQNhkaeV8EF2rZqy9m5whs+jIx1tUdyJPJXLyZCNr3Q8t4sQyek6q
1+imN6KUEIHrLveuYq1Lvmw3lt52vRzvWwucYV0EHSbx3G0b6hErAgMBAAE=
-----END RSA PUBLIC KEY-----
`
// pkcs1 标准 pem 格式的私钥
var privateKeyPkcs1Pem = `
-----BEGIN RSA PRIVATE KEY-----
MIICYAIBAAKBgQCywP2lBJUsarz1J5QuAPFGjYerccq45S7IVuP8FIFmSAQW76e8
lY+DoguZm228rzqhJUDYZGnlfBBdq2asvZucIbPoyMdbVHciTyVy8mQja90PLeLE
MnpOqtfopjeilBCB6y73rmKtS75sN5bedr0c71sLnGFdBB0m8dxtG+oRKwIDAQAB
AoGADOrlaYdrQEp2XUD+9FQdG3we0cTnYXUubEvbLdxNfZa2tPGcrYQhWuHa9L7G
r1v6YKrQhNK81Fii1iIMvBnzkVIakhSYvC294yyEZG+fYJcXuZWzoF0+YUrlFP0b
vG5JOpDcUN4YG+tG924AbhyPL0AJkX0BEElSWaFhVtnTxAECRQC4fMLIzE2hCq9F
UmR59YDSHasPUVDWuq0eXG+P/0Kp9x5ZUDjZcojcBhpsJBQbx9P4ygyiYj4uUw3O
SA8X/fZHxqmg/QI9APgLR5Uz5Veaj1PguhkoKB3384PnrrKoFD+wgc6H7Qib9aKG
KT0x5dKswZefyE/PF+Qi7hMWiO18FK2HRwJEb/eQREvyhV21uE3kGzzL3ToSWq6Q
cHJFpVqWfv9+Fyea7LvKdPaVZ2vw11ciOSYTWThPaLJVaMoRY/PJ7Va+BRvmUYUC
PQCO06fnYReZRxVq3gcqvzXCc+kTtg+hLilitxc3vosdnvhlGk2awCWvFuzuiwID
+qKuKfLeqOY1oXIirbcCRGtG4PspKLAQMO6jI7bFUc5if9UKo6TGeu39E3qtv4jW
NW6qObPBJ9R1gurMqPUT9g630xjZdZxz6ac9Z7FfgjpMV0Fe
-----END RSA PRIVATE KEY-----
`
var key = new NodeRSA();
key.setOptions({ encryptionScheme: "pkcs1" }); // 设置填充模式,默认 pkcs1_oaep
// 导入密钥,传入参数格式:语法标准-密钥类型-输出格式,即 scheme-[key_type]-[output_type]
key.importKey(publicKeyPkcs1Pem, "pkcs1-public-pem"); // 公钥语法标准支持 pkcs1、pkcs8,输出格式支持 pem、der
key.importKey(privateKeyPkcs1Pem, "pkcs1-private-pem"); // 私钥语法标准支持 pkcs1、pkcs8,输出格式支持 pem、der
// RSA 加解密
var data = "spiderapi.cn - 虫术";
var resultEncrypted = key.encrypt(data, "base64");
var resultDecrypted = key.decrypt(resultEncrypted, "utf8");
console.log("RSA PKCS1Padding 加密结果: ", resultEncrypted)
console.log("RSA PKCS1Padding 解密结果: ", resultDecrypted)
```
</code-block>

<code-block title="加密解密 3️⃣">
```javascript
// ✅ 安装依赖:npm install jsencrypt,官方文档:https://github.com/travist/jsencrypt
// ❗ 如果在 Node 环境中使用,会遇到报错 window is not defined,需要在 \node_modules\jsencrypt\bin\jsencrypt.js 添加代码:window = global;
// ❌ padding 填充方式默认为 RSA_PKCS1_PADDING,不支持其他填充方式
var JSEncrypt = require("jsencrypt");
// pkcs1 标准 pem 格式的公钥
var publicKeyPkcs1Pem = `
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALLA/aUElSxqvPUnlC4A8UaNh6txyrjlLshW4/wUgWZIBBbvp7yVj4Oi
C5mbbbyvOqElQNhkaeV8EF2rZqy9m5whs+jIx1tUdyJPJXLyZCNr3Q8t4sQyek6q
1+imN6KUEIHrLveuYq1Lvmw3lt52vRzvWwucYV0EHSbx3G0b6hErAgMBAAE=
-----END RSA PUBLIC KEY-----
`
// pkcs1 标准 pem 格式的私钥
var privateKeyPkcs1Pem = `
-----BEGIN RSA PRIVATE KEY-----
MIICYAIBAAKBgQCywP2lBJUsarz1J5QuAPFGjYerccq45S7IVuP8FIFmSAQW76e8
lY+DoguZm228rzqhJUDYZGnlfBBdq2asvZucIbPoyMdbVHciTyVy8mQja90PLeLE
MnpOqtfopjeilBCB6y73rmKtS75sN5bedr0c71sLnGFdBB0m8dxtG+oRKwIDAQAB
AoGADOrlaYdrQEp2XUD+9FQdG3we0cTnYXUubEvbLdxNfZa2tPGcrYQhWuHa9L7G
r1v6YKrQhNK81Fii1iIMvBnzkVIakhSYvC294yyEZG+fYJcXuZWzoF0+YUrlFP0b
vG5JOpDcUN4YG+tG924AbhyPL0AJkX0BEElSWaFhVtnTxAECRQC4fMLIzE2hCq9F
UmR59YDSHasPUVDWuq0eXG+P/0Kp9x5ZUDjZcojcBhpsJBQbx9P4ygyiYj4uUw3O
SA8X/fZHxqmg/QI9APgLR5Uz5Veaj1PguhkoKB3384PnrrKoFD+wgc6H7Qib9aKG
KT0x5dKswZefyE/PF+Qi7hMWiO18FK2HRwJEb/eQREvyhV21uE3kGzzL3ToSWq6Q
cHJFpVqWfv9+Fyea7LvKdPaVZ2vw11ciOSYTWThPaLJVaMoRY/PJ7Va+BRvmUYUC
PQCO06fnYReZRxVq3gcqvzXCc+kTtg+hLilitxc3vosdnvhlGk2awCWvFuzuiwID
+qKuKfLeqOY1oXIirbcCRGtG4PspKLAQMO6jI7bFUc5if9UKo6TGeu39E3qtv4jW
NW6qObPBJ9R1gurMqPUT9g630xjZdZxz6ac9Z7FfgjpMV0Fe
-----END RSA PRIVATE KEY-----
`
var encryptor = new JSEncrypt();
encryptor.setPublicKey(publicKeyPkcs1Pem);
encryptor.setPrivateKey(privateKeyPkcs1Pem);
// RSA 加解密,填充方式只支持 RSA_PKCS1_PADDING
var data = "spiderapi.cn - 虫术";
var resultEncrypted = encryptor.encrypt(data);
var resultDecrypted = encryptor.decrypt(resultEncrypted);
console.log("RSA PKCS1Padding 加密结果: ", resultEncrypted)
console.log("RSA PKCS1Padding 解密结果: ", resultDecrypted)
```
</code-block>
</code-group>

Expand Down

0 comments on commit 3f39a19

Please sign in to comment.