事出有因

在完成创建数据源的需求时,需要对数据源的用户密码等相关敏感信息进行加密传递,Vue前端加密,Java后端和Python后端解密。经过方案调研后,最终确定采用RSA加解密的方案。

Bug现场

由Java后端通过工具生成公私钥字符串,并将公钥给到前端,前端在创建数据源利用公钥对用户输入的敏感信息进行加密,Java服务接收请求进行校验,并保存。Python服务需要在使用数据源时进行敏感信息解密,此时遇到的问题是,经java服务解密校验通过,而Python则无法进行解密。

迎刃而解

根因分析:

经过对Java服务和Python服务的加解密实现进行深入研究,发现Java中使用的PKCS8,而Python中只有PKCS1,因为此协议不匹配,导致无法解密。

PKCS #1 为 OpenSSH 默认使用的加密标准
PKCS #8 为 Java 默认使用的加密标准

方案1尝试:试图在python的工具包中找到关于PKCS8的实现,未果。

方案2尝试:试图在Java的工具包中找到关于PKCS1的实现,未果。

方案3尝试:经过一番搜索,找到一种思路,将PKCS8生成的私钥转换成PKCS1的私钥,再进行尝试,成功。

完成流程总结

  • 使用openssl生成秘钥
1
openssl genrsa -out private.pem 1024
  • 查看私钥
1
2
3
4
5
6
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDAQWZDPB5q3B0hKNO8Schw4ihwrJAITWHMMImjSKcRUSbAaKsM
3kLhI8Sx7mPHVW21W6X4MOWyPLAlAOfX3DWNSHBThsJKOEeIlNmZ68MjCE6hWx+W
fpUtPWmj8CBNUuZrHmAip4/2TTMHEfJPPzRA5FBmzjH7cn/5w+QlZjeINwIDAQAB
...
-----END RSA PRIVATE KEY-----
  • 生成查看公钥
1
openssl rsa -in private.pem -out public.pem -pubout
  • 将PKCS1的私钥转换为PKCS8
1
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform pem -nocrypt -out pkcs8.pem
  • 配置到代码中,即可

扩展

Python代码片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import base64
# pip install pycryptodome
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA

PUBLIC_KEY = "MRFM4nWu25GsG+gLwkqClZk1DUva\nKfkKK73ZQ8mcLI3Pbx8zaX+1P38S7KUIOK8QI9gzsIZ0RMamOmrwl4ECAwEAAQ=="
PRIVATE_KEY = "MIIBOQIBAA8mcLI3Pbx8z\naX+1P38S7KUIOK8QI9gzsIZ0RMamOmrwl4ECAwEAAQJAdZzQARRCEZ1P9GkIVbVa\naYWcXSe53Paet+YeteIN3xJELq4qYYuYAGlF2HmP9wpKZHXHdmlGEs8fi+pUMEGP\n8QIhAOYVlA5Jihog5jSEb5S2Id7Z7LjrusLs67MtjjQzj3ddAiEAm1QpjN/QzB4l\nRxIHG2BlzwmU/vSJYGH8ePkRMuC8knUCIHF+43HIxN7uq5/sVD4/OaX8SdFONupA\nhGP2bNdDN9nhAiATKYXauD3VAJ8Orn2r9e95ZDA6Z8aO2mfAMNHbWfhJhQIgCtFH\nzTtqqn/mgfftb/9g3vYyBRAz90vlKAaHgd9/U/k="


def decrypt(data: str, private_key: str) -> str:
convert_data = base64.b64decode(bytes(data, encoding="utf8"))
rsa_key = RSA.importKey(base64.b64decode(private_key))
cipher = PKCS1_v1_5.new(rsa_key)
return str(cipher.decrypt(convert_data, "DecryptError"), encoding='utf-8')


def encrypt(data: str, public_key: str) -> str:
rsa_key = RSA.importKey(base64.b64decode(public_key))
cipher = PKCS1_v1_5.new(rsa_key)
result_data = cipher.encrypt(bytes(data, encoding="utf8"))
return str(base64.b64encode(result_data), encoding='utf-8')


if __name__ == '__main__':
encrypt_result = encrypt('123456', PUBLIC_KEY)
print(encrypt_result)
# encrypt_result = 'RZRbgTEEN9hXVdRab3wbCycIwWqBcGjRk9V2V0nDhKZwjgQ4pWHOu6A=='
decrypt_data = decrypt(encrypt_result, PRIVATE_KEY)
print(decrypt_data)

RSA的秘钥类型汇总

PKCS 版本 名称 简介
PKCS #1 2.1 RSA密码编译标准 定义了RSA的数理基础、公/私钥格式,以及加/解密、签/验章的流程。1.5版本曾经遭到攻击。
PKCS #3 1.4 DH密钥协议标准 规范以DH密钥协议为基础的密钥协议标准。
PKCS #5 2.0 密码基植加密标准 参见RFC 2898与PBKDF2。
PKCS #7 1.5 密码消息语法标准 规范了以公开密钥基础设施(PKI)所产生之签名/密文之格式。
PKCS #8 1.2 私钥消息表示标准 Apache读取证书私钥的标准。
PKCS #12 1.0 个人消息交换标准 定义了包含私钥与公钥证书的文件格式。

RSA的格式转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 生成PKCS1私钥
openssl genrsa -out private.pem 1024

# PKCS1私钥转换为PKCS8
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform pem -nocrypt -out pkcs8.pem

# PKCS8私钥转换为PKCS1
openssl rsa -in pkcs8.pem -out pkcs1.pem

# 从PKCS1私钥中生成PKCS8公钥
openssl rsa -in private.pem -pubout -out public.pem

# 从PKCS8私钥中生成PKCS8公钥
openssl rsa -in pkcs8.pem -pubout -out public_pkcs8.pem

# 从PKCS8公钥转换PKCS1公钥
openssl rsa -pubin -in public_pkcs8.pem -RSAPublicKey_out

# 从PKCS1公钥转换PKCS8公钥
openssl rsa -RSAPublicKey_in -in pub_pkcs1.pem -pubout

本站由 sswfive 使用 Stellar 1.42.0 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站总访问量