在这篇文章中,介绍了如何使用飞天信诚的加密狗设备进行加密解密。
但是文章的最后,有一个遗憾,就是需要借助官方给的php代码来进行解密,自己尝试了几次用python实现,但是总是失败,今天终于发现了解决之道。
需要安装一个pycryptodome。
1
| pip3 install pycryptodome -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
|
最后的代码:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| def check_rsa_code(encrypted_str: str) -> str: """ 使用公钥解密(等效于 PHP 的 openssl_public_decrypt) 适配 PKCS#1 v1.5 两种 padding 格式 (0x01/0x02)
:param encrypted_str: URL 编码 + Base64 编码的密文 :return: 解密后的明文字符串 """ public_key_pem = """-----BEGIN PUBLIC KEY----- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxx -----END PUBLIC KEY-----"""
encrypted_str = unquote(encrypted_str) encrypted_bytes = base64.b64decode(encrypted_str)
rsa_key = RSA.import_key(public_key_pem) n = rsa_key.n e = rsa_key.e
cipher_int = int.from_bytes(encrypted_bytes, byteorder="big") plain_int = pow(cipher_int, e, n)
k = (rsa_key.size_in_bits() + 7) // 8 plain_bytes = plain_int.to_bytes(k, byteorder="big")
if len(plain_bytes) > 2 and plain_bytes[0] == 0x00: if plain_bytes[1] == 0x01: sep_idx = plain_bytes.find(b"\x00", 2) if sep_idx > 0: plain_bytes = plain_bytes[sep_idx+1:] elif plain_bytes[1] == 0x02: sep_idx = plain_bytes.find(b"\x00", 2) if sep_idx > 0: plain_bytes = plain_bytes[sep_idx+1:] else: plain_bytes = plain_bytes.lstrip(b"\x00") else: plain_bytes = plain_bytes.lstrip(b"\x00")
return plain_bytes.decode("utf-8")
|
这样就解决了这一问题,完全不再依赖PHP了,真好!
困扰了四年的问题,就这样解决了~