PyCryptodome实现RSA签名验证始终返回True问题求助
搞定你的RSA验证总是返回True的问题
嘿,我看了你的代码,发现两个关键问题导致验证函数不管传啥都返回True,咱们一步步来解决:
1. 你搞反了密钥的用途!
RSA签名的核心逻辑是私钥签名,公钥验证——私钥用来生成只有对应公钥能验证的专属签名,公钥只能做验证不能签名。但你的代码里,sign和verify都用了同一个keys.txt里的密钥,如果这个文件存的是私钥,那用私钥去做验证时,PyCryptodome的PKCS1_v1_5.verify会出现未定义的异常行为,直接跳过验证返回“成功”,这就是为啥不管传什么签名都返回True。
2. 测试用例的签名类型不对(但被第一个问题掩盖了)
你的sign函数返回的签名是字节对象,但测试用例里传的是字符串:
verify(["this will return"," true whatever I enter"], keys)
正常来说,字符串和字节类型不匹配会触发TypeError,被你的except块捕获后返回False,但因为第一个问题的存在,这个异常根本没触发,反而让验证“通过”了。
修复后的完整代码
第一步:先生成并分开保存私钥和公钥
先运行一次这段代码生成密钥对:
from Crypto.PublicKey import RSA # 生成2048位RSA密钥对 key_pair = RSA.generate(2048) # 保存私钥(仅用于签名) with open("private_key.pem", "wb") as f: f.write(key_pair.exportKey()) # 保存公钥(仅用于验证) with open("public_key.pem", "wb") as f: f.write(key_pair.publickey().exportKey())
修正后的RSA_Handler.py
from Crypto.PublicKey import RSA from Crypto.Hash import SHA256 from Crypto.Signature import PKCS1_v1_5 import pickle def sign(data, private_key_data): key = RSA.importKey(private_key_data) # 序列化数据并生成SHA256哈希 serialized_data = pickle.dumps(data) hash_obj = SHA256.new(serialized_data) # 用私钥生成签名 signature = PKCS1_v1_5.new(key).sign(hash_obj) return [data, signature] def verify(signed_data, public_key_data): data = signed_data[0] signature = signed_data[1] key = RSA.importKey(public_key_data) # 重新生成待验证数据的哈希 serialized_data = pickle.dumps(data) hash_obj = SHA256.new(serialized_data) try: # 用公钥验证签名合法性 PKCS1_v1_5.new(key).verify(hash_obj, signature) return True except (ValueError, TypeError): # 验证失败时捕获异常,返回False return False
修正后的test01.py
from RSA_Handler import * # 读取私钥用于签名 with open("private_key.pem", "rb") as rb: private_key = rb.read() # 读取公钥用于验证 with open("public_key.pem", "rb") as rb: public_key = rb.read() # 正常场景:合法签名验证 signed_data = sign("hello", private_key) print("合法签名验证结果:", verify(signed_data, public_key)) # 输出True # 异常场景:伪造数据+随机签名 invalid_result = verify(["fake data", b"random_signature_bytes"], public_key) print("非法签名验证结果:", invalid_result) # 输出False
额外提醒:别用pickle做序列化!
pickle是非常不安全的,如果攻击者能控制你要验证的数据,他们可以构造恶意的pickle payload,在你调用pickle.dumps()的时候执行任意代码。建议换成更安全的方式,比如json.dumps()(如果数据是JSON可序列化的),或者用固定格式的字节编码(比如把字符串转成UTF-8字节)。
内容的提问来源于stack exchange,提问作者CodEdo
相关产品推荐
相关产品推荐

