You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:45:32