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

Go与Ruby跨语言RSA签名验证失败问题排查

问题根源与解决方案:Go签名Ruby验证失败的核心原因

核心问题:签名与验证的数据源不匹配

你的Go代码中,签名操作是对原始JSON序列化后的字节流进行哈希和签名:

func (r request) Signature(key *rsa.PrivateKey) string {
  data, err := json.Marshal(&r) // 处理原始JSON字节流
  if err != nil {
    panic(err)
  }
  hashed := sha256.Sum256(data)
  // ...签名逻辑
}

但Ruby端验证时,直接用Base64编码后的字符串作为验证数据源:

return p_key.verify('sha256', Base64.strict_decode64(signature), message)

两者处理的核心数据完全不一致,这是验证失败的根本原因。

两种修复方案

方案1:修改Ruby端(推荐,保持Go端逻辑不变)

将接收到的Base64编码消息解码为原始JSON字节流,再进行验证:

def validate(public_key, message, signature)
  p_key = OpenSSL::PKey::RSA.new(public_key)
  # 解码Base64得到原始JSON数据,作为验证的核心数据源
  original_data = Base64.strict_decode64(message)
  return p_key.verify('sha256', Base64.strict_decode64(signature), original_data)
end

方案2:修改Go端(保持Ruby端逻辑不变)

调整Go的签名逻辑,对Base64编码后的字符串进行哈希和签名:

func (r request) Signature(key *rsa.PrivateKey) string {
  // 先获取Base64编码后的字符串
  encoded := r.ToBase64()
  // 对Base64字符串进行哈希
  hashed := sha256.Sum256([]byte(encoded))
  signature, err := rsa.SignPKCS1v15(nil, key, crypto.SHA256, hashed[:])
  if err != nil {
    panic(err)
  }
  return base64.StdEncoding.Strict().EncodeToString(signature)
}

额外排查要点

  • JSON序列化一致性:确保Go和Ruby的JSON输出完全一致(字段顺序、空格、引号格式等)。可分别打印两边原始JSON字节流的SHA256哈希值对比:
    • Go端:fmt.Printf("%x", sha256.Sum256(data))
    • Ruby端:puts Digest::SHA256.hexdigest(original_data)
      若哈希值不同,需统一序列化规则(比如Ruby使用JSON.generate而非to_json,避免额外空格)。
  • Base64编码一致性:你当前代码已使用strict模式(无换行、标准字符集),这部分无需调整。
  • 密钥格式:确认公钥为PKCS#1格式,Go的x509.ParsePKCS1PrivateKey与Ruby的OpenSSL::PKey::RSA.new格式匹配,这部分逻辑是正确的。

内容的提问来源于stack exchange,提问作者lfrg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:34:54