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

Golang与Java生成的PKCS#1v15 RSA签名不一致,求解决建议

RSA签名不一致问题解决(Java vs Golang)

在实现基于PKCS#1v15的RSA签名时,先对原始数据做MD5哈希转十六进制字符串,再用SHA256WithRSA签名,Golang生成的签名始终和Java版本不一致,导致服务器返回签名错误。

问题根源

1. SHA256摘要处理逻辑不一致

Java中SHA256WithRSA签名算法的逻辑是:先对要签名的字节数据计算SHA256摘要,再用RSA PKCS#1v15对该摘要签名。
而你的Golang代码中,直接将MD5十六进制字符串的字节传入rsa.SignPKCS1v15并指定crypto.SHA256参数——这个参数的含义是「传入的字节已经是SHA256摘要」,所以Go会直接对这些字节做RSA签名,跳过了SHA256哈希步骤,和Java的逻辑完全相反。

2. Base64 URL安全编码的填充处理差异

Java的Base64.encodeBase64URLSafeString会自动去除Base64编码末尾的填充字符=,而Golang默认的base64.URLEncoding.EncodeToString会保留这些填充字符,导致最终的签名字符串不一致。

修正后的Golang代码

import (
    "crypto/md5"
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "crypto"
    "encoding/base64"
    "encoding/hex"
    "fmt"
)

func GetSignature(data []byte, pk *rsa.PrivateKey) (string, error) {
    // 第一步:MD5哈希转十六进制字符串,和Java逻辑对齐
    m := md5.New()
    _, err := m.Write(data)
    if err != nil {
        return "", err
    }
    encoded := hex.EncodeToString(m.Sum(nil))
    fmt.Println(encoded)

    // 第二步:对十六进制字符串的UTF-8字节计算SHA256摘要,补全Java中SHA256WithRSA的哈希步骤
    sha256Hash := sha256.New()
    _, err = sha256Hash.Write([]byte(encoded))
    if err != nil {
        return "", err
    }
    sha256Digest := sha256Hash.Sum(nil)

    // 第三步:用RSA PKCS#1v15签名SHA256摘要
    signature, err := rsa.SignPKCS1v15(rand.Reader, pk, crypto.SHA256, sha256Digest)
    if err != nil {
        return "", err
    }

    // 第四步:使用无填充的Base64 URL安全编码,对齐Java的处理逻辑
    return base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(signature), nil
}

验证要点

  • 确保Java和Golang使用同一套RSA私钥,且私钥格式一致(比如均为PKCS#8格式)。
  • 打印MD5转十六进制的字符串,确认两者完全一致(排除数据编码差异)。
  • 打印签名前的SHA256摘要,确认Java和Golang计算结果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:13:20