将Node.js crypto签名逻辑转为Python jwt实现时出现签名错误的技术问询
问题分析与解决方案
你的问题出在错误使用了JWT编码来实现单纯的RSA-SHA256签名。Node.js代码是直接对payload的JSON字符串进行签名,而jwt.encode会生成符合JWT规范的令牌(包含header、payload和签名三部分,用.分隔),两者的签名输入完全不同,自然会导致签名不匹配。
Node.js代码的核心逻辑
先拆解一下网关提供的Node.js代码做了什么:
- 读取PEM格式的私钥
- 创建RSA-SHA256签名器
- 将payload序列化为无空格分隔的JSON字符串,并去除首尾空白字符
- 对该字符串进行签名,输出Base64编码的结果
正确的Python实现
要和Node.js行为完全一致,需要严格对齐每一步的操作:
1. 安装依赖
确保你已经安装了cryptography库(这是Python处理加密操作的标准库):
pip install cryptography
2. 完整Python代码
import json import base64 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding # 定义需要签名的payload actual = { "IntraTransferRqHeader": { "CorporateID": "XXX", "CorpReferenceNumber": "47165454456" }, "IntraTransferRqBody": { "AccountNumber": "05100004061100", "DebitCurrency": "SAR", "BeneficiaryAccountNumber": "30008776337526", "TransferAmount": "100.23", "TransferCurrency": "SAR", "Description": "Transfer fund to beneficiary", "AMLPurposeCode": "BC" } } # 读取PEM私钥 private_key_path = "/etc/ssl/nginx/snbcsr.key" with open(private_key_path, "rb") as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=None, backend=None # 无需显式指定后端(cryptography v3.0+默认自动处理) ) # 生成与Node.js一致的JSON字符串:无空格分隔符+去除首尾空白 payload_str = json.dumps(actual, separators=(',', ':')).strip() # 执行RSA-SHA256签名 signature_bytes = private_key.sign( payload_str.encode("utf-8"), padding.PKCS1v15(), # Node.js的createSign默认使用PKCS#1 v1.5填充 hashes.SHA256() ) # 转换为Base64编码的签名(与Node.js输出格式一致) signature_base64 = base64.b64encode(signature_bytes).decode("utf-8") print(signature_base64)
关键注意事项
- JSON字符串一致性:Node.js的
JSON.stringify默认生成无空格的JSON(如{"a":1,"b":2}),而Python的json.dumps默认会添加空格(如{"a": 1, "b": 2})。必须用separators=(',', ':')参数消除空格,否则签名输入会不一致。 - 填充算法:Node.js的
crypto.createSign("RSA-SHA256")默认使用PKCS#1 v1.5填充,Python中对应padding.PKCS1v15()。 - 字符编码:确保字符串以UTF-8编码为字节流后再签名,与Node.js的默认编码一致。
内容的提问来源于stack exchange,提问作者Mostafa Mohamed
相关产品推荐
相关产品推荐

