Skip to content

Commit

Permalink
add: rsa algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
TRHX committed Mar 11, 2024
1 parent 5e45d44 commit 6ff8d34
Showing 1 changed file with 235 additions and 4 deletions.
239 changes: 235 additions & 4 deletions docs/03.辅助查询/04.加密算法/07.rsa.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ RSA 密钥的模数是公钥和私钥中的一个重要参数,通常用大素
- 公钥使用 `spki` 标准,得到的公钥以 `-----BEGIN PUBLIC KEY-----` 开头;
- 私钥使用 `pkcs1` 标准,得到的私钥以 `-----BEGIN RSA PRIVATE KEY-----` 开头;
- 私钥使用 `pkcs8` 标准,得到的私钥以 `-----BEGIN PRIVATE KEY-----` 开头。
- 私钥使用 `pkcs1` 标准,如果对私钥进行了加密,则得到的私钥包含 `Proc-Type``DEK-Info` 字段;
- 私钥使用 `pkcs1` 标准,如果对私钥进行了加密,则得到的私钥以 `-----BEGIN RSA PRIVATE KEY-----` 开头,但内容里包含 `Proc-Type``DEK-Info` 字段;
- 私钥使用 `pkcs8` 标准,如果对私钥进行了加密,则得到的私钥以 `-----BEGIN ENCRYPTED PRIVATE KEY-----` 开头。

---
Expand Down Expand Up @@ -104,6 +104,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
:::

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

<code-group>
<code-block title="生成密钥(推荐)1️⃣" active>
Expand Down Expand Up @@ -324,6 +325,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
</code-group>

### JavaScript <Badge text="Node.js"/> <Badge text="ECMAScript 5.1+"/>
<br/>

<code-group>
<code-block title="生成密钥(推荐)1️⃣" active>
Expand Down Expand Up @@ -499,16 +501,237 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we

### Golang <Badge text="1.0+"/>

```go
// ✅ 无需安装依赖,官方文档:https://pkg.go.dev/crypto
// ❌ 公钥指数不支持自定义,默认 655370x10001),该值是除了 13517257 之外的最小素数
// ❌ 密钥输出格式不支持 jwk、openssh
// ❌ 对私钥进行签名、加密,只支持 pkcs1 标准的私钥,不支持 pkcs8 标准的私钥

package main

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
)

func main() {
rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println("Generate key failed:", err)
return
}

// 私钥输出格式 der,私钥语法标准支持 pkcs1 (MarshalPKCS1PrivateKey)、pkcs8 (MarshalPKCS8PrivateKey)
privateKeyDER := x509.MarshalPKCS1PrivateKey(rsaKey)

// 可选操作:使用密码加密私钥,注意,EncryptPEMBlock 方法正在被弃用,该方法只能加密 pkcs1 标准的私钥
// blockType 参数指定密钥的标头,与私钥语法标准对应:pkcs1 加密对应 "RSA PRIVATE KEY"
// alg 参数指定加密算法,参见:https://pkg.go.dev/crypto/x509#PEMCipher
password := []byte("spiderapi")
encryptedPrivateKeyPEMBlock, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", privateKeyDER, password, x509.PEMCipherAES256)
if err != nil {
fmt.Println("Private key encrypt failed:", err)
return
}
encryptedPrivateKeyPEM := pem.EncodeToMemory(encryptedPrivateKeyPEMBlock)

// 将私钥转为 pem 格式
// Type 参数指定密钥的标头,与私钥语法标准对应:pkcs1 对应 "RSA PRIVATE KEY",pkcs8 对应 "PRIVATE KEY"
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyDER,
})

// 公钥输出格式 der,公钥语法标准支持 pkcs1 (MarshalPKCS1PublicKey)、spki (MarshalPKIXPublicKey)
publicKeyPEM, err := x509.MarshalPKIXPublicKey(&rsaKey.PublicKey)
if err != nil {
fmt.Println("Public Key encoding failed:", err)
return
}

// 将公钥转为 pem 格式
// Type 参数指定密钥的标头,与公钥语法标准对应:pkcs1 对应 "RSA PUBLIC KEY",spki 对应 "PUBLIC KEY"
publicKey := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyPEM,
})

fmt.Println("RSA 公钥(spki、pem):\n\n", string(publicKey))
fmt.Println("RSA 私钥(pkcs1、pem):\n\n", string(privateKeyPEM))
fmt.Println("RSA 加密后的私钥(pkcs1、pem、aes-256-cbc):\n\n", string(encryptedPrivateKeyPEM))
}

/*
RSA 公钥(spki、pem):

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1P94ik8uUca0kq613hw0
dy0i/dALloDg4I32lkk7eWV/obe2I/qEY2Nz7SmmY8VZeJUfiQuAVuOxFYI7rKPM
4LvSvkKC5xcWho1319eyZKC1AYlXKHjQPrUXNrDwmM1racGw9NopFg/GyikhaZiT
vsW7NM3O3HN26irQXFO0C7vypIaZtOIB9YVA9YFpBLNnINczRyekltoZqhL4j/Of
C+VuXZOxL0wfJOML7axF4Fwt7XSir8BPJMoEc2KVFYxMMd06tfJMRzvHOEckOaob
ZLrZjHM4YzDr32ClpgCazx7QWsBiMo3AqMuNO+LBV/VynsZPymgehIiDRGr7+S0F
ywIDAQAB
-----END PUBLIC KEY-----

RSA 私钥(pkcs1、pem):

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA1P94ik8uUca0kq613hw0dy0i/dALloDg4I32lkk7eWV/obe2
I/qEY2Nz7SmmY8VZeJUfiQuAVuOxFYI7rKPM4LvSvkKC5xcWho1319eyZKC1AYlX
KHjQPrUXNrDwmM1racGw9NopFg/GyikhaZiTvsW7NM3O3HN26irQXFO0C7vypIaZ
tOIB9YVA9YFpBLNnINczRyekltoZqhL4j/OfC+VuXZOxL0wfJOML7axF4Fwt7XSi
r8BPJMoEc2KVFYxMMd06tfJMRzvHOEckOaobZLrZjHM4YzDr32ClpgCazx7QWsBi
Mo3AqMuNO+LBV/VynsZPymgehIiDRGr7+S0FywIDAQABAoIBAQDSQhYFwkAhLZvX
KGwTg5gvBPmDv7mQqkxSnxEKLeRt48noI+fDAGtriSNIvFKqLogxxlNI/3eDTmTi
rJqnw1Jdjkts0U9TO7FaxY/GHADX4OSNTbwiEZDQNgdiT6xRyoX78d3y9uCUDKLZ
sVxwVtOSALLaX0eSytBaPEVOvrn+0Y06x/jiKhHvw1LCNc+E0lp3myrwW+6f0LCJ
KD4dc5AWop64psKwDXP2t8bcyK5uhLjZYiSKjSi+7y8kCNmN0LimYjbjt8nvHo1J
s24BbfE/MwrXhuV2/1ODBezPoOLBm51rzt9syHHnQBh95LPdLPr5N5r5uPvkToDu
X5eM5ughAoGBAPxvHiyoKjWTc2cYw2exsabp2OOkKHH5BP8VBErEvTzmbzr9mKFR
PG0ZcxLnSPux9xaoExdNd+NPnVWl5sR3ZLezGLSaeZw5RagTlkQ/YOXZ6b7mWZcE
hpZNlvSyG3dIP63N4ONwTCpRrjyndv/sSGARrHsp4I1mv+23cQaQfvADAoGBANgB
vUh8Uekq6SuJ2MmvX63cq5kK6BejWfEk6xFlHOTE49yzorn8yJoy1dBoO5BN1VcZ
NUPSNt7PP0HR0BAgX5pKun/dAIs9+Y4HJPojeLkkhFgjx0FxQrQ2usIAaqAwZlpC
rzClr7/8ZO5jeZMdfxcqE43KNrWOWGleyYQnr9yZAoGAcMPCmvhUQrKnrrplMAE0
9vcnqClA2AkBrmFZFX1le7sEnTmD4SxE7gecXCltdOI/GqPiQ1qb37NE+Wmu+LzN
BTLAKo2HHb6H21lEmyAkzQjXXivQgaHH7YSjlpOpqVNg/uclOvSDUbRDPV0hz5lh
i2jZv/spEIGB41M67k/GJLkCgYAzRZZsUjYPJoRaNUoj9WC8oBiLJy+YDMoYly7E
3j9RffqoNGt3wizLjS17XoJk6lSta+pcwtULZh4ZvXepnEWVFg/WsdqjMn6926xH
Q4wwRh6z3So6umue4y7JRdgJVfO1kQaMgYeKBpreivYcmW/FS9OAYHND/Rm3SSyE
FfeEYQKBgAVICBeE9LrMzoPwaTiGcRwEbx13Mo2SgzrKiwSY960Ewlu5t17197e0
EEqJ1Y+ItIA+4j9XEMu6e1hV56Zy9rNEOyUZSB83tB1TQTzasbTDLfh0vJZmbudF
6VTo4nST7kLzJYJe4A1SF2gLKasrbBL0Ye22PK2AuwHIWca2e+OS
-----END RSA PRIVATE KEY-----

RSA 加密后的私钥(pkcs1、pem、aes-256-cbc):

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,3a42d48c94f2f06b0354a04de8247917

6rr+ZAQXJXS3zv9gZUbSp+Ft1ngcjshRrlKYcbeXaBPbWwfwE0iwG47aSJIpAvR1
ac2NhCTyq8ATqbjrhdf4dSHGYwpLJZzdQ7X+g3FmvJpLJMglaLhM2ls+IN+ofOS+
Bp9DwCSvdvTQEocHqTImXS98Bb6pr49FdJmQMma8pm2U73fIro8apVTDwQD/iHIB
nEQ6+ZvUIqp+spEifYle0d1q1ADU/ZavqMt21bDhz56Ccf++6unXk+BhYVGj1WX0
LYmZS8yRVHWDPk19i8yOCeMfZSS929JhCIsRVWYomxSVdwQP6h2iG4tU2+5mvDo1
Pbr4BrLKjFCO3ixhbjmW+ySNoNB/dNkkNd4eaBvmUoC1A/sNz3rJQR2Kl5r9kOCi
iVzh7hpPHTGmW9GY3PBYsIIE84HwrMpmcHHX/qWg/P5B/qAqOXQb4n8UozwuICdn
w/i8c/k6YwOndYkIUqJjUg4KmWTdAQkyaCceBi/i4p9XgWZvq7MKQSQw0K9SeBoz
Q7zUmJjFBtaLN/N3ckyuTeWQOZtGlVjK/rZKFy99RsMum//HX+S8XciUgs2p8A0f
HMrIpgFg3XQSW5el4ykNdS216hEmMtUWfrGhn5D4UEDIHMRF5j9abR2T2BhKbh8m
KcagOdBRRdKBH8JU8l3NT+tSYI+DpbMFH7X1QwfZNVlChAZblipOT9PpW4LbuZhv
nIDU7KjodaV1JrRSOs/+9ferPKxkCXsGj3n5W/9wfbwUnChhhuYXvBVbNd48Os9m
j5jQFVdcxQNe4UyYa7L3KaEzbp9GwX6MsUbiATH7jqEqfero50oTEznWKh4GQtrZ
UL5QhESMEb+3X+JC1nu3aFzbvm+Y0dRjj5bi/R4wk1CAMIOWyT/iYSz+Oe9CNsVA
gKQ5pjY4fwrLjwXVDsm52sQT99V6fVWbUXmg1iNrZ3hbLZ7sGZ0iK6ecz+x4zzMG
m7/7Lbdb0wwGD+K5RPtDmmR9PvwCbxdfQGy8sLyUnUIB1btLRyTnPTXseuIZyFLu
BKWTeLWhqya2h7B9iDYxQq1ySKAJaD8n6Rp+plUqJiyaO/RYcJRwun/U/GVuSfct
YT1BytgfGqM6GL0S+RzFuaG7EYgg8vRuKwHw9rjdaIIz//cL/Y8YCJhJIhmVd7GJ
NE5f+DXPvhhMf/12CF/rcGy6VVGnhlCHN+6dHWeodcbQVbuMJaznasqTk8NuWV75
fZ70FmdHlJHHzTmZ/bQe6qp/1IKLYxa5v8lZEG9ER2hQ2uSjOzLt0nRc8K/HX7xA
Fi+8mRxjsOok75QKfJHNyCXL33hxDclnGbqANUp8bE45h1F3RWnQ60QYc6/EVE9Y
FOKqqOMrTjcIebJN4zYNUDT1OClB6VdyaJLmPtzIYDE07qwWoHdGWVQmrofR/hzL
5+c3LY2AtxQvIyWJc7BmP6lp46KmoUcc9BLkydi5bp9XDM2OgZGjHN9pkdhqdyNH
3zkUzf5dimvaPLHHlKtz1MNF7LTkPRJX94ATq1PDhsgX9OX0lvI10lb+MCI483Mq
IOIIMVT9256lXj+b+q+AhxkhSg4vMLmv28/O8+QZehwcqM1CeA4qzafLGziA/6tl
-----END RSA PRIVATE KEY-----
*/
```

## 解析密钥
### Python <Badge text="3.0+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
<code-block title="解析密钥 1️⃣" active>
</code-block>

<code-block title="纯源码">
<code-block title="解析密钥 2️⃣">
</code-block>
</code-group>

## 解析密钥
### JavaScript <Badge text="Node.js"/> <Badge text="ECMAScript 5.1+"/>
<br/>

<code-group>
<code-block title="解析密钥 1️⃣" active>
```javascript
// ✅ 安装依赖:npm install node-forge,官方文档:https://github.com/digitalbazaar/forge

var forge = require("node-forge");

var publicKeyPEM = `
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCl7HWuXcOH9I/Bud7dplYxHOEC
D82fJv1WJKADhmILCxDLJLVkueBQfwUItPELF3RLhs+3+XNYfGiz7PPPhxV1pey5
jrHT8zw8InrNRwlDeCyx/Q+ETpSpQImvILf0RBHtnOgVpb41uhKF24wGH4q7+faN
w6cBVKhFn+fuItSGfQIDAQAB
-----END PUBLIC KEY-----
`

var privateKeyPEM = `
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCl7HWuXcOH9I/Bud7dplYxHOECD82fJv1WJKADhmILCxDLJLVk
ueBQfwUItPELF3RLhs+3+XNYfGiz7PPPhxV1pey5jrHT8zw8InrNRwlDeCyx/Q+E
TpSpQImvILf0RBHtnOgVpb41uhKF24wGH4q7+faNw6cBVKhFn+fuItSGfQIDAQAB
AoGBAKSmc1kmfoQJciZh1gDJsTpnV/l9ySQnwrma+pbE4cHnpzCPKtnbgfcfNNWh
CJljGupfyvzbs1SZkCUL/B1yBR3uAbWw5G0uzJo61wYciufnQA1/lu3JyEyLeSxb
eFOIkuI8Ce0SCPT01+6sR77EA0VtUA+0Ak7OI4EvElFPn0qBAkEA8SvKXG6suLFL
9TjUH2B1XDwMxQFw7JOOhAyLcbNJMLgqMhHuqvTW/T4oxTQh7LbDMP977ZDnkmdt
L8S7zAHHsQJBALAgOFkbNNH4FzBQtxyWEu6+D0ZhvhIAIoH0pDBdoIO9vKalRgWy
vV6YsI3NujjBjz1p7g3Zb/zliA3vH9ieqo0CQQCdlOVmvBIzo/Vjx7wivF4y5DHb
z/M/QbMPaTr8Eg+yu8MmcD0oi06mriTppgS8rTahH26UbehB6z6Wxc+Hn2ohAkEA
r2GmOrToyBzvmmEFtiWK/MmtlDxIdMxFkHr39GGHMSiC7r6tF4eBIu2RAePWiCXW
aSVOs+PNrFs0PAvd/mshEQJAYpxilxZI7hJT89Qne6CgPXqqZf0sFX0FeR9AJaj1
g2c+B9GgZ+Nou4ne4WXjOVUWZuuch7yqn3XoxeQT4/xaCw==
-----END RSA PRIVATE KEY-----
`

// 解码 PEM 格式的公钥和密钥
var publicKey = forge.pki.publicKeyFromPem(publicKeyPEM);
var privateKey = forge.pki.privateKeyFromPem(privateKeyPEM);

// 获取模数(modulus),使用 16 进制字符串表示,从公钥和私钥中均可获取,且值是一样的
var modulus = publicKey.n.toString(16); // 或者 privateKey.n.toString(16);

// 计算密钥的位数,即模数(modulus)的位数,16 进制转换为位数时每个字符代表 4 位
var keyLength = modulus.length * 4;

// 获取公钥指数
var publicExponent = publicKey.e.toString();

// 获取私钥指数
var privateExponent = privateKey.d.toString(16);

console.log("模数为: ", modulus); // a5ec75ae5dc387f48fc1b9dedda656311ce1020fcd9f26fd5624a00386620b0b10cb24b564b9e0507f0508b4f10b17744b86cfb7f973587c68b3ecf3cf871575a5ecb98eb1d3f33c3c227acd470943782cb1fd0f844e94a94089af20b7f44411ed9ce815a5be35ba1285db8c061f8abbf9f68dc3a70154a8459fe7ee22d4867d
console.log("密钥(模数)位数为: ", keyLength); // 1024
console.log("公钥指数为: ", publicExponent); // 65537 (0x10001)
console.log("私钥指数为: ", privateExponent); // a4a67359267e8409722661d600c9b13a6757f97dc92427c2b99afa96c4e1c1e7a7308f2ad9db81f71f34d5a10899631aea5fcafcdbb3549990250bfc1d72051dee01b5b0e46d2ecc9a3ad7061c8ae7e7400d7f96edc9c84c8b792c5b78538892e23c09ed1208f4f4d7eeac47bec403456d500fb4024ece23812f12514f9f4a81
```
</code-block>

<code-block title="解析密钥 2️⃣">
</code-block>
</code-group>

### Golang <Badge text="1.0+"/>
<br/>

<code-group>
<code-block title="解析密钥 1️⃣" active>
</code-block>

<code-block title="解析密钥 2️⃣">
</code-block>
</code-group>

## 转换密钥
### Python <Badge text="3.0+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
Expand All @@ -519,6 +742,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
</code-group>

### JavaScript <Badge text="Node.js"/> <Badge text="ECMAScript 5.1+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
Expand All @@ -529,6 +753,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
</code-group>

### Golang <Badge text="1.0+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
Expand All @@ -540,6 +765,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we

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

<code-group>
<code-block title="依赖库" active>
Expand All @@ -550,6 +776,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
</code-group>

### JavaScript <Badge text="Node.js"/> <Badge text="ECMAScript 5.1+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
Expand All @@ -560,6 +787,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
</code-group>

### Golang <Badge text="1.0+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
Expand All @@ -571,6 +799,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we

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

<code-group>
<code-block title="依赖库" active>
Expand All @@ -581,13 +810,15 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we
</code-group>

### JavaScript <Badge text="Node.js"/> <Badge text="ECMAScript 5.1+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
</code-block>
</code-group>

### Golang <Badge text="1.0+"/>
<br/>

<code-group>
<code-block title="依赖库" active>
Expand Down

0 comments on commit 6ff8d34

Please sign in to comment.