RSA3072+SHA384+PSS签名验证失败排查(Python Crypto模块)
RSA 3072+SHA384+PSS签名验证失败的问题排查与解决方案
核心问题原因
你遇到的验证失败,大概率是PSS填充的参数不匹配——PyCrypto的PKCS1_PSS.new()默认参数可能和签名方使用的参数不一致,尤其是在SHA384这种非默认哈希算法场景下:
- 默认情况下,
PKCS1_PSS.new()会用与签名哈希相同的算法做MGF1,但部分旧版本库可能存在逻辑疏漏; - Salt长度默认是
PSS.MAX_LENGTH,但很多签名实现会用与哈希摘要长度一致的salt(SHA384对应48字节); - 手动构造公钥时,若模数
n或指数e的字节序、格式处理错误(比如把小端字节流当成大端解析),也会导致公钥无效。
修正后的PyCrypto验证代码
显式指定所有PSS参数,确保和签名方对齐:
from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_PSS from Crypto.Hash import SHA384, MGF1 def verify_signature(data, signature, pubkey_path=None, n=None, e=None): # 加载或构造公钥 if pubkey_path: with open(pubkey_path, 'rb') as f: key = RSA.import_key(f.read()) elif n and e: # 确保n和e是整数,若从字节流解析需用大端 key = RSA.construct((n, e)) else: raise ValueError("Either pubkey_path or n+e must be provided") # 显式指定PSS参数:MGF1用SHA384,salt长度等于哈希摘要长度 h = SHA384.new(data) verifier = PKCS1_PSS.new( key, mgf=MGF1.MGF1Function(SHA384), salt_length=SHA384.digest_size ) try: verifier.verify(h, signature) return True except (ValueError, TypeError): return False
OpenSSL命令行替代方案
如果PyCrypto的问题无法解决,直接用OpenSSL命令行验证更可靠,参数完全对齐:
# 假设待验证数据是data.bin,签名文件是signature.bin,公钥是pubkey.pem openssl dgst -sha384 -verify pubkey.pem \ -sigopt rsa_padding_mode:pss \ -sigopt rsa_pss_saltlen:-1 \ -signature signature.bin data.bin
-sigopt rsa_pss_saltlen:-1表示使用与哈希摘要长度相同的salt(和代码里的salt_length=SHA384.digest_size对应);- 验证成功会输出
Verified OK,失败则输出Verification Failure。
Python中基于Cryptography库的替代实现
PyCrypto已停止维护,推荐用更现代的cryptography库,参数逻辑更清晰:
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import serialization def verify_with_cryptography(data, signature, pubkey_path=None, n=None, e=None): # 加载公钥 if pubkey_path: with open(pubkey_path, "rb") as f: public_key = serialization.load_pem_public_key(f.read()) elif n and e: # 从模数和指数构造公钥,需确保n和e是整数 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers public_key = RSAPublicNumbers(e, n).public_key() else: raise ValueError("Either pubkey_path or n+e must be provided") try: public_key.verify( signature, data, padding.PSS( mgf=padding.MGF1(hashes.SHA384()), salt_length=hashes.SHA384.digest_size ), hashes.SHA384() ) return True except: return False
内容的提问来源于stack exchange,提问作者Dhruva
相关产品推荐
相关产品推荐

