Python3实现RSA/ECB/PKCS1Padding解密报非私钥错误如何解决
报错原因
- 直接原因:PyCryptodome库的
PKCS1_v1_5.decrypt()方法设计上只允许传入RSA私钥对象执行解密操作,你代码中传入的是公钥对象,因此触发类型错误。 - Java代码可正常运行的原因:Java的
Cipher实现没有做密钥用途的强制校验,你代码中instance.init(2, generatePublic)的参数2对应Cipher.DECRYPT_MODE,实际执行的是公钥解密逻辑(对应加密侧是用配对的RSA私钥加密得到密文),和标准RSA公钥加密、私钥解密的流程相反。
解决方法
我们可以利用RSA的运算原理手动实现公钥解密+PKCS1填充去除逻辑,修改后可正常运行的代码如下:
from Crypto.PublicKey import RSA from base64 import b64decode import math public_key_str = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC32VkPYUKYszF665DH0jRuCuyKPqf4pkmcUWXOp8CZkNriew18iLiNGBAtDXhmtdzj6bEaBbxkNixzLfNMtNQw53bfW5lgRC91nG4fiK085sJ8CkdL22PIhRWO75x2pwk+Wqlx5N3OxVV0oS76dI7/pCqTCfqJec7BMH820Im5AwIDAQAB" encrypted_data_base64 = "qKVan83WWFmVRVASPZ2Io8iM1qs/rowwHH4zh7NNcrh8544hhJr1fKE2PkogAKZWD8mjoO1x4AhRSkrLMsTB0m6V+ZsayLOLiIpCh5hsybaH3NdPKPhMyIqAUdw3au2Zcl76b/4FeNvP9ay/S0niXzQMVBTgHcHhrfjquqQnoXc=" # 导入公钥,获取公钥参数e和n pub_key = RSA.importKey(b64decode(public_key_str)) e = pub_key.e n = pub_key.n # 把密文转成大整数 cipher_int = int.from_bytes(b64decode(encrypted_data_base64), byteorder='big') # 执行公钥解密运算:m = c^e mod n plain_int = pow(cipher_int, e, n) # 把整数转回字节串,长度和密钥长度一致(1024位密钥对应128字节) plain_padded = plain_int.to_bytes(math.ceil(n.bit_length()/8), byteorder='big') # 去除PKCS1 v1.5填充:PKCS1填充格式是0x00 0x02 [随机非0字节] 0x00 [明文] if plain_padded[0] != 0 or plain_padded[1] != 2: raise ValueError("无效的PKCS1填充") # 找到0x00分隔符的位置 sep_idx = plain_padded.index(b'\x00', 2) plaintext = plain_padded[sep_idx+1:] print(plaintext.decode('utf-8'))
运行上述代码即可得到和Java代码一致的输出结果:rtmp://wfjsh.sryhm.cn/5showcam/7362473_1636710891?auth_key=1636719851-0-0-85e0853c941754dff7809599215a6076
内容的提问来源于stack exchange,提问作者kuzminpx59ruslan650
相关产品推荐
相关产品推荐

