使用PyCryptodome加密消息并签名:签名验证失败问题排查
PyCryptodome实现PKI签名验证失败问题修复
问题根源分析
你的代码存在以下几个关键错误导致验证失败:
- verify_msg函数参数缺失:
verify方法需要传入待验证的哈希对象和签名值,原代码遗漏了签名参数。 - 验证逻辑混淆:验证签名时,应该用原始加密消息作为验证依据,而非把签名本身当作消息传入。
- 解密对象错误:解密操作的目标应该是加密后的消息,而非签名数据。
- 变量名拼写错误:
singed_msg应为signed_msg(拼写失误)。
修正后的完整代码
from Crypto.Cipher import AES, PKCS1_OAEP from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Random import get_random_bytes from Crypto.Signature import pkcs1_15 from Crypto.Util.Padding import pad, unpad def sign_msg(msg: bytes, priv_key): hashed_msg = SHA256.new(msg) signed_msg = pkcs1_15.new(priv_key).sign(hashed_msg) return signed_msg def verify_msg(msg: bytes, signature: bytes, pub_key): hashed_msg = SHA256.new(msg) try: # 补充签名参数 pkcs1_15.new(pub_key).verify(hashed_msg, signature) except (ValueError, TypeError): return False return True shared_key = get_random_bytes(16) shared_iv = get_random_bytes(16) # 客户端侧逻辑 client_privkey = RSA.import_key(open('client_side/private_key.pem').read()) client_pubkey = RSA.import_key(open('client_side/public_key.pem').read()) msg_to_sign = input("Message to sign: ") enc_msg = AES.new(shared_key, AES.MODE_CBC, shared_iv).encrypt(pad(msg_to_sign.encode('utf-8'), 16)) print("Encrypted message:") print(enc_msg) # 修正变量名拼写 signed_msg = sign_msg(enc_msg, client_privkey) print("Signed Message: ") print(signed_msg) #----------------------------------------------------------------------------------------# # 服务器侧逻辑 server_pubkey = RSA.import_key(open('server_side/public_key.pem').read()) server_privkey = RSA.import_key(open('server_side/private_key.pem').read()) print("Received Encrypted Message: ") print(enc_msg) print("Received Signature: ") print(signed_msg) # 传入原始加密消息和签名进行验证 if verify_msg(enc_msg, signed_msg, client_pubkey): print("Message VERIFIED!") # 解密原始加密消息而非签名 dec_msg = AES.new(shared_key, AES.MODE_CBC, shared_iv).decrypt(unpad(enc_msg, 16)) print("Decrypted msg: ") print(dec_msg.decode('utf-8')) else: print("Message not verified..")
关键修正说明
- verify_msg函数:新增
signature参数,调用verify方法时传入该参数,完成哈希与签名的匹配验证。 - 服务器验证逻辑:调用
verify_msg时传入enc_msg(原始加密消息)和signed_msg(签名),而非仅传入签名。 - 解密操作:修正解密对象为
enc_msg,并在解密后用decode('utf-8')将字节转为字符串。 - 变量名修正:将
singed_msg改为signed_msg,规范命名。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

