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 12, 2024
1 parent 6ff8d34 commit f636171
Showing 1 changed file with 279 additions and 34 deletions.
313 changes: 279 additions & 34 deletions docs/03.辅助查询/04.加密算法/07.rsa.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,37 +643,141 @@ IOIIMVT9256lXj+b+q+AhxkhSg4vMLmv28/O8+QZehwcqM1CeA4qzafLGziA/6tl
```

## 解析密钥

::: details 关于解析 RSA 密钥
PKCS1 RSA 公钥和私钥格式的 [ASN.1](https://www.rfc-editor.org/rfc/rfc3447#appendix-C) 规范如下:

```text
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
```

为了提高效率,许多流行的加密库都使用基于中国剩余定理(CRT)来优化加速解密和签名,所以 prime1、prime2 等值已预先计算并存储为私钥的一部分,如果给定一对 RSA 密钥,那么我们就可以从中解析出以下信息:

- <mark>**keySize**</mark>:密钥的位数,即模数(modulus)的位数
- <mark>**modulus**</mark>:模数 $N=p*q$,一个大素数的乘积,用于生成公钥和私钥,参见前面生成密钥中对模数的解释
- <mark>**publicExponent**</mark>:公钥指数 $e$,参见前面生成密钥中对公钥指数的解释
- <mark>**privateExponent**</mark>:私钥指数 $d$,参见前面生成密钥中对私钥指数的解释
- <mark>**prime1**</mark>:RSA 算法中的第一个质数 $p$,用于生成私钥
- <mark>**prime2**</mark>:RSA 算法中的第二个质数 $q$,用于生成私钥
- <mark>**exponent1**</mark>:私钥指数模 $p-1$ 的模反元素,即 $d\bmod{(p-1)}$
- <mark>**exponent2**</mark>:私钥指数模 $q-1$ 的模反元素,即 $d\bmod{(q-1)}$
- <mark>**coefficient**</mark>:模反元素之间的系数,即 $q^-1\bmod p$

---

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

公钥加密标准 PKCS#1 rfc3447:[https://www.rfc-editor.org/rfc/rfc3447](https://www.rfc-editor.org/rfc/rfc3447)<br/>
使用中国剩余定理(CRT)来加速 RSA 算法的计算:[https://www.di-mgt.com.au/crt_rsa.html](https://www.di-mgt.com.au/crt_rsa.html)<br/>
维基百科 Using the Chinese remainder algorithm:[https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Padding_schemes](https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Padding_schemes)
:::

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

<code-group>
<code-block title="解析密钥 1️⃣" active>
</code-block>
<code-block title="解析密钥(推荐) 1️⃣" active>
```python
# ✅ 安装依赖 pip install pycryptodome,官方文档:https://pycryptodome.readthedocs.io/

<code-block title="解析密钥 2️⃣">
from Crypto.PublicKey import RSA


# 注意 """ 之后要紧跟着密钥标头,如果换行可能会因为无法解析导致报错:ValueError: RSA key format is not supported
public_key_pem = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCl7HWuXcOH9I/Bud7dplYxHOEC
D82fJv1WJKADhmILCxDLJLVkueBQfwUItPELF3RLhs+3+XNYfGiz7PPPhxV1pey5
jrHT8zw8InrNRwlDeCyx/Q+ETpSpQImvILf0RBHtnOgVpb41uhKF24wGH4q7+faN
w6cBVKhFn+fuItSGfQIDAQAB
-----END PUBLIC KEY-----
"""

private_key_pem = """-----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-----
"""

# 解析私钥和公钥
public_key = RSA.importKey(public_key_pem)
private_key = RSA.importKey(private_key_pem)

# 获取模数(modulus),使用 16 进制字符串表示,从公钥和私钥中均可获取,且值是一样的
modulus = hex(public_key.n)[2:] # 或者 private_key.n

# 计算密钥的位数,即模数(modulus)的位数,16 进制转换为位数时每个字符代表 4 位
key_length = len(modulus) * 4

# 获取公钥指数
public_exponent = hex(public_key.e)[2:]

# 获取私钥指数
private_exponent = hex(private_key.d)[2:]

# 获取私钥其他参数
prime1 = hex(private_key.p)[2:]
prime2 = hex(private_key.q)[2:]
exponent1 = hex(private_key.d % (private_key.p - 1))[2:]
exponent2 = hex(private_key.d % (private_key.q - 1))[2:]
coefficient = hex(pow(private_key.q, -1, private_key.p))[2:]

print("(16 进制)模数: ", modulus) # a5ec75ae5dc387f48fc1b9dedda656311ce1020fcd9f26fd5624a00386620b0b10cb24b564b9e0507f0508b4f10b17744b86cfb7f973587c68b3ecf3cf871575a5ecb98eb1d3f33c3c227acd470943782cb1fd0f844e94a94089af20b7f44411ed9ce815a5be35ba1285db8c061f8abbf9f68dc3a70154a8459fe7ee22d4867d
print("(16 进制)密钥 & 模数位数: ", key_length) # 1024
print("(16 进制)公钥指数: ", public_exponent) # 0x10001 (65537)
print("(16 进制)私钥指数: ", private_exponent) # a4a67359267e8409722661d600c9b13a6757f97dc92427c2b99afa96c4e1c1e7a7308f2ad9db81f71f34d5a10899631aea5fcafcdbb3549990250bfc1d72051dee01b5b0e46d2ecc9a3ad7061c8ae7e7400d7f96edc9c84c8b792c5b78538892e23c09ed1208f4f4d7eeac47bec403456d500fb4024ece23812f12514f9f4a81
print("(16 进制)私钥 prime1: ", prime1) # f12bca5c6eacb8b14bf538d41f60755c3c0cc50170ec938e840c8b71b34930b82a3211eeaaf4d6fd3e28c53421ecb6c330ff7bed90e792676d2fc4bbcc01c7b1
print("(16 进制)私钥 prime2: ", prime2) # b02038591b34d1f8173050b71c9612eebe0f4661be12002281f4a4305da083bdbca6a54605b2bd5e98b08dcdba38c18f3d69ee0dd96ffce5880def1fd89eaa8d
print("(16 进制)私钥 exponent1: ", exponent1) # 9d94e566bc1233a3f563c7bc22bc5e32e431dbcff33f41b30f693afc120fb2bbc326703d288b4ea6ae24e9a604bcad36a11f6e946de841eb3e96c5cf879f6a21
print("(16 进制)私钥 exponent2: ", exponent2) # af61a63ab4e8c81cef9a6105b6258afcc9ad943c4874cc45907af7f46187312882eebead17878122ed9101e3d68825d669254eb3e3cdac5b343c0bddfe6b2111
print("(16 进制)私钥 coefficient: ", coefficient) # 629c62971648ee1253f3d4277ba0a03d7aaa65fd2c157d05791f4025a8f583673e07d1a067e368bb89dee165e339551666eb9c87bcaa9f75e8c5e413e3fc5a0b
```
</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
<code-block title="解析密钥 2️⃣">
```python
# ✅ 安装依赖 pip install cryptography,要求 Python 3.7+,官方文档:https:#cryptography.io/

var forge = require("node-forge");
from cryptography.hazmat.primitives import serialization

var publicKeyPEM = `

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

var privateKeyPEM = `
private_key_pem = """
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCl7HWuXcOH9I/Bud7dplYxHOECD82fJv1WJKADhmILCxDLJLVk
ueBQfwUItPELF3RLhs+3+XNYfGiz7PPPhxV1pey5jrHT8zw8InrNRwlDeCyx/Q+E
Expand All @@ -689,35 +793,176 @@ IOIIMVT9256lXj+b+q+AhxkhSg4vMLmv28/O8+QZehwcqM1CeA4qzafLGziA/6tl
aSVOs+PNrFs0PAvd/mshEQJAYpxilxZI7hJT89Qne6CgPXqqZf0sFX0FeR9AJaj1
g2c+B9GgZ+Nou4ne4WXjOVUWZuuch7yqn3XoxeQT4/xaCw==
-----END RSA PRIVATE KEY-----
`
"""

// 解码 PEM 格式的公钥和密钥
var publicKey = forge.pki.publicKeyFromPem(publicKeyPEM);
var privateKey = forge.pki.privateKeyFromPem(privateKeyPEM);
# 解析私钥和公钥
public_key = serialization.load_pem_public_key(public_key_pem.encode())
private_key = serialization.load_pem_private_key(private_key_pem.encode(), password=None)

public_numbers = public_key.public_numbers()
private_numbers = private_key.private_numbers()

# 获取模数(modulus),使用 16 进制字符串表示,从公钥和私钥中均可获取,且值是一样的
modulus = hex(public_numbers.n)[2:] # 或者 private_numbers.public_numbers.n

# 计算密钥的位数,即模数(modulus)的位数,16 进制转换为位数时每个字符代表 4 位
key_length = len(modulus) * 4

# 获取公钥指数
public_exponent = hex(public_numbers.e)[2:]

# 获取私钥指数
private_exponent = hex(private_numbers.d)[2:]

# 获取私钥其他参数
prime1 = hex(private_numbers.p)[2:]
prime2 = hex(private_numbers.q)[2:]
exponent1 = hex(private_numbers.dmp1)[2:]
exponent2 = hex(private_numbers.dmq1)[2:]
coefficient = hex(private_numbers.iqmp)[2:]

print("(16 进制)模数: ", modulus) # a5ec75ae5dc387f48fc1b9dedda656311ce1020fcd9f26fd5624a00386620b0b10cb24b564b9e0507f0508b4f10b17744b86cfb7f973587c68b3ecf3cf871575a5ecb98eb1d3f33c3c227acd470943782cb1fd0f844e94a94089af20b7f44411ed9ce815a5be35ba1285db8c061f8abbf9f68dc3a70154a8459fe7ee22d4867d
print("(16 进制)密钥 & 模数位数: ", key_length) # 1024
print("(16 进制)公钥指数: ", public_exponent) # 0x10001 (65537)
print("(16 进制)私钥指数: ", private_exponent) # a4a67359267e8409722661d600c9b13a6757f97dc92427c2b99afa96c4e1c1e7a7308f2ad9db81f71f34d5a10899631aea5fcafcdbb3549990250bfc1d72051dee01b5b0e46d2ecc9a3ad7061c8ae7e7400d7f96edc9c84c8b792c5b78538892e23c09ed1208f4f4d7eeac47bec403456d500fb4024ece23812f12514f9f4a81
print("(16 进制)私钥 prime1: ", prime1) # f12bca5c6eacb8b14bf538d41f60755c3c0cc50170ec938e840c8b71b34930b82a3211eeaaf4d6fd3e28c53421ecb6c330ff7bed90e792676d2fc4bbcc01c7b1
print("(16 进制)私钥 prime2: ", prime2) # b02038591b34d1f8173050b71c9612eebe0f4661be12002281f4a4305da083bdbca6a54605b2bd5e98b08dcdba38c18f3d69ee0dd96ffce5880def1fd89eaa8d
print("(16 进制)私钥 exponent1: ", exponent1) # 9d94e566bc1233a3f563c7bc22bc5e32e431dbcff33f41b30f693afc120fb2bbc326703d288b4ea6ae24e9a604bcad36a11f6e946de841eb3e96c5cf879f6a21
print("(16 进制)私钥 exponent2: ", exponent2) # af61a63ab4e8c81cef9a6105b6258afcc9ad943c4874cc45907af7f46187312882eebead17878122ed9101e3d68825d669254eb3e3cdac5b343c0bddfe6b2111
print("(16 进制)私钥 coefficient: ", coefficient) # 629c62971648ee1253f3d4277ba0a03d7aaa65fd2c157d05791f4025a8f583673e07d1a067e368bb89dee165e339551666eb9c87bcaa9f75e8c5e413e3fc5a0b
```
</code-block>

<code-block title="解析密钥 3️⃣">
```python
# ✅ 安装依赖 pip install rsa,官方文档:https://stuvel.eu/python-rsa-doc/

// 获取模数(modulus),使用 16 进制字符串表示,从公钥和私钥中均可获取,且值是一样的
var modulus = publicKey.n.toString(16); // 或者 privateKey.n.toString(16);
# ❌ 不支持解析 spki 语法标准的公钥,只支持 pkcs1
# ❌ 不支持解析 pkcs8 语法标准的私钥,只支持 pkcs1

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

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

// 获取私钥指数
var privateExponent = privateKey.d.toString(16);
public_key_pem = """
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALLA/aUElSxqvPUnlC4A8UaNh6txyrjlLshW4/wUgWZIBBbvp7yVj4Oi
C5mbbbyvOqElQNhkaeV8EF2rZqy9m5whs+jIx1tUdyJPJXLyZCNr3Q8t4sQyek6q
1+imN6KUEIHrLveuYq1Lvmw3lt52vRzvWwucYV0EHSbx3G0b6hErAgMBAAE=
-----END RSA PUBLIC KEY-----
"""

console.log("模数为: ", modulus); // a5ec75ae5dc387f48fc1b9dedda656311ce1020fcd9f26fd5624a00386620b0b10cb24b564b9e0507f0508b4f10b17744b86cfb7f973587c68b3ecf3cf871575a5ecb98eb1d3f33c3c227acd470943782cb1fd0f844e94a94089af20b7f44411ed9ce815a5be35ba1285db8c061f8abbf9f68dc3a70154a8459fe7ee22d4867d
console.log("密钥(模数)位数为: ", keyLength); // 1024
console.log("公钥指数为: ", publicExponent); // 65537 (0x10001)
console.log("私钥指数为: ", privateExponent); // a4a67359267e8409722661d600c9b13a6757f97dc92427c2b99afa96c4e1c1e7a7308f2ad9db81f71f34d5a10899631aea5fcafcdbb3549990250bfc1d72051dee01b5b0e46d2ecc9a3ad7061c8ae7e7400d7f96edc9c84c8b792c5b78538892e23c09ed1208f4f4d7eeac47bec403456d500fb4024ece23812f12514f9f4a81
private_key_pem = """
-----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-----
"""

# 解析私钥和公钥
private_key = rsa.PrivateKey.load_pkcs1(private_key_pem.encode(), 'PEM')
public_key = rsa.PublicKey.load_pkcs1(public_key_pem.encode(), 'PEM')

# 获取模数(modulus),使用 16 进制字符串表示,从公钥和私钥中均可获取,且值是一样的
modulus = hex(public_key.n)[2:] # 或者 private_key.n

# 计算密钥的位数,即模数(modulus)的位数,16 进制转换为位数时每个字符代表 4 位
key_length = len(modulus) * 4

# 获取公钥指数
public_exponent = hex(public_key.e)[2:]

# 获取私钥指数
private_exponent = hex(private_key.d)[2:]

# 获取私钥其他参数
prime1 = hex(private_key.p)[2:]
prime2 = hex(private_key.q)[2:]
exponent1 = hex(private_key.d % (private_key.p - 1))[2:]
exponent2 = hex(private_key.d % (private_key.q - 1))[2:]
coefficient = hex(pow(private_key.q, -1, private_key.p))[2:]

print("(16 进制)模数: ", modulus) # b2c0fda504952c6abcf527942e00f1468d87ab71cab8e52ec856e3fc148166480416efa7bc958f83a20b999b6dbcaf3aa12540d86469e57c105dab66acbd9b9c21b3e8c8c75b5477224f2572f264236bdd0f2de2c4327a4eaad7e8a637a2941081eb2ef7ae62ad4bbe6c3796de76bd1cef5b0b9c615d041d26f1dc6d1bea112b
print("(16 进制)密钥 & 模数位数: ", key_length) # 1024
print("(16 进制)公钥指数: ", public_exponent) # 0x10001 (65537)
print("(16 进制)私钥指数: ", private_exponent) # ceae569876b404a765d40fef4541d1b7c1ed1c4e761752e6c4bdb2ddc4d7d96b6b4f19cad84215ae1daf4bec6af5bfa60aad084d2bcd458a2d6220cbc19f391521a921498bc2dbde32c84646f9f609717b995b3a05d3e614ae514fd1bbc6e493a90dc50de181beb46f76e006e1c8f2f4009917d0110495259a16156d9d3c401
print("(16 进制)私钥 prime1: ", prime1) # b87cc2c8cc4da10aaf45526479f580d21dab0f5150d6baad1e5c6f8fff42a9f71e595038d97288dc061a6c24141bc7d3f8ca0ca2623e2e530dce480f17fdf647c6a9a0fd
print("(16 进制)私钥 prime2: ", prime2) # f80b479533e5579a8f53e0ba1928281df7f383e7aeb2a8143fb081ce87ed089bf5a286293d31e5d2acc1979fc84fcf17e422ee131688ed7c14ad8747
print("(16 进制)私钥 exponent1: ", exponent1) # 6ff790444bf2855db5b84de41b3ccbdd3a125aae90707245a55a967eff7e17279aecbbca74f695676bf0d7572239261359384f68b25568ca1163f3c9ed56be051be65185
print("(16 进制)私钥 exponent2: ", exponent2) # 8ed3a7e761179947156ade072abf35c273e913b60fa12e2962b71737be8b1d9ef8651a4d9ac025af16ecee8b0203faa2ae29f2dea8e635a17222adb7
print("(16 进制)私钥 coefficient: ", coefficient) # 6b46e0fb2928b01030eea323b6c551ce627fd50aa3a4c67aedfd137aadbf88d6356eaa39b3c127d47582eacca8f513f60eb7d318d9759c73e9a73d67b15f823a4c57415e
```
</code-block>

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

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

```javascript
// ✅ 安装依赖:npm install node-forge,官方文档:https://github.com/digitalbazaar/forge

// ❌ 不支持解析私钥的 prime1、prime2、exponent1、exponent2、coefficient 参数

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(16);

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

console.log("(16 进制)模数: ", modulus); // a5ec75ae5dc387f48fc1b9dedda656311ce1020fcd9f26fd5624a00386620b0b10cb24b564b9e0507f0508b4f10b17744b86cfb7f973587c68b3ecf3cf871575a5ecb98eb1d3f33c3c227acd470943782cb1fd0f844e94a94089af20b7f44411ed9ce815a5be35ba1285db8c061f8abbf9f68dc3a70154a8459fe7ee22d4867d
console.log("(16 进制)密钥 & 模数位数: ", keyLength); // 1024
console.log("(16 进制)公钥指数: ", publicExponent); // 0x10001 (65537)
console.log("(16 进制)私钥指数: ", privateExponent); // a4a67359267e8409722661d600c9b13a6757f97dc92427c2b99afa96c4e1c1e7a7308f2ad9db81f71f34d5a10899631aea5fcafcdbb3549990250bfc1d72051dee01b5b0e46d2ecc9a3ad7061c8ae7e7400d7f96edc9c84c8b792c5b78538892e23c09ed1208f4f4d7eeac47bec403456d500fb4024ece23812f12514f9f4a81
```

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

Expand Down

0 comments on commit f636171

Please sign in to comment.