跨语言RSA-SHA256-PSS签名验证失败:JSON对象验证不通过
Python与Go RSA-SHA256-PSS签名互验失败的解决方法
问题根源
签名验证失败的核心原因是Python和Go对JSON对象/结构体的序列化结果不一致:
- Python的
json.dumps默认会在键值对、逗号后添加空格(如{"name": "Foo", "age": 12}) - Go的
json.Marshal(包括你使用的goccy/go-json默认行为)生成的是无空格的紧凑JSON(如{"name":"Foo","age":12})
两者生成的字节串完全不同,而签名是基于序列化后的字节串计算的,自然无法通过验证。
修复步骤
1. 修改Python代码,生成紧凑无空格的JSON
在json.dumps中指定separators=(',', ':')参数,强制生成和Go一致的紧凑JSON:
def sign_user(message) -> str: # 关键修改:生成无空格的紧凑JSON message_json = json.dumps(message, separators=(',', ':')) message_byts = message_json.encode("utf-8") # 后续加载私钥、签名的代码保持不变 key_file = open("private_key.pem", "rb") private_key = serialization.load_pem_private_key( key_file.read(), password=None, backend=default_backend() ) signature = private_key.sign( message_byts, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256(), ) signature_base64 = base64.b64encode(signature).decode("utf-8") print("\n\n", signature_base64, "\n\n") return signature_base64
2. 确保Go序列化规则匹配
你的Go代码使用goccy/go-json的json.Marshal默认就是紧凑序列化,无需修改,但要确保没有开启任何格式化(如缩进)选项:
func verifySignatureUser(sign string, data User){ // 默认生成紧凑JSON,和修改后的Python代码输出一致 dataBytes, err := json.Marshal(data) if err != nil { fmt.Print(err) } verified, err := VerifySignature(sign, dataBytes) if err != nil { fmt.Println(err) } fmt.Println(verified) }
3. 额外校验项
- 键顺序:确保Python字典的键顺序和Go结构体的字段顺序完全一致(你的代码中已经满足:
name→age→email) - 数据类型:Python的
int和Go的uint序列化后无差异,若涉及浮点型需保证精度一致 - 编码:两边均使用UTF-8编码(代码已满足)
验证
修改Python代码后重新生成签名,用Go代码验证即可通过。
内容的提问来源于stack exchange,提问作者Luqman Jr
相关产品推荐
相关产品推荐

