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

Go中使用RSA/ECB/PKCS1Padding加密对接银联失败,如何解决?

解决Go与Java RSA/ECB/PKCS1Padding加密结果不一致问题

导致Go和Java加密结果无法对接银联的核心是字符串编码、证书解析格式两个关键细节差异,逐一修正即可:

1. 字符串编码不匹配

Java中plantext.getBytes()默认采用系统平台编码(Windows下为GBK,Linux/macOS下为UTF-8),而Go中[]byte(plantext)固定使用UTF-8编码。银联接口通常要求统一使用GBK编码,这是最常见的不匹配原因。

修正方案:
引入GBK编码库,将明文转为GBK字节数组再加密:

import (
    "golang.org/x/text/encoding/simplifiedchinese"
    "golang.org/x/text/transform"
    "io"
)

// 字符串转GBK字节数组
func strToGBK(s string) ([]byte, error) {
    encoder := simplifiedchinese.GBK.NewEncoder()
    result, _, err := transform.String(encoder, s)
    if err != nil {
        return nil, err
    }
    return []byte(result), nil
}

加密时替换原字节转换逻辑:

gbkPlaintext, err := strToGBK("6122005564598")
if err != nil {
    // 处理编码错误
}
encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, gbkPlaintext)

2. 证书解析格式差异

Java代码直接解码纯Base64格式的DER证书(无PEM头尾标记),而Go的pem.Decode仅支持带-----BEGIN CERTIFICATE-----/-----END CERTIFICATE-----的PEM格式证书。如果你的证书源和Java端一致(纯Base64),需跳过PEM解码,直接解析DER格式:

// 假设certBase64是纯Base64的证书字符串(无PEM头尾)
derBytes, err := base64.StdEncoding.DecodeString(certBase64)
if err != nil {
    // 处理解码错误
}
cert, err := x509.ParseCertificate(derBytes)
if err != nil {
    // 处理证书解析错误
}
pubKey := cert.PublicKey.(*rsa.PublicKey)

3. Base64编码一致性验证

Java的Base64.encodeBase64String和Go的base64.StdEncoding.EncodeToString均为标准Base64编码(无换行),这部分通常无需调整。若Java端使用URL安全Base64,需替换为Go的base64.URLEncoding。

完整可运行Go代码示例

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/base64"
    "errors"
    "log"
    "golang.org/x/text/encoding/simplifiedchinese"
    "golang.org/x/text/transform"
    "io"
)

func strToGBK(s string) ([]byte, error) {
    encoder := simplifiedchinese.GBK.NewEncoder()
    result, _, err := transform.String(encoder, s)
    if err != nil {
        return nil, err
    }
    return []byte(result), nil
}

func encryptWithUnionPayCert(certBase64, plaintext string) (string, error) {
    // 解析DER格式证书
    derBytes, err := base64.StdEncoding.DecodeString(certBase64)
    if err != nil {
        return "", err
    }
    cert, err := x509.ParseCertificate(derBytes)
    if err != nil {
        return "", err
    }
    pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
    if !ok {
        return "", errors.New("not RSA public key")
    }

    // 转换明文为GBK编码
    gbkData, err := strToGBK(plaintext)
    if err != nil {
        return "", err
    }

    // RSA PKCS#1 v1.5加密
    encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, gbkData)
    if err != nil {
        return "", err
    }

    return base64.StdEncoding.EncodeToString(encrypted), nil
}

func main() {
    // 替换为你的银联公钥证书纯Base64字符串
    unionPayCert := "你的证书Base64内容"
    plaintext := "6122005564598"
    
    encryptedStr, err := encryptWithUnionPayCert(unionPayCert, plaintext)
    if err != nil {
        log.Fatalf("加密失败: %v", err)
    }
    log.Println("加密结果:", encryptedStr)
}

验证方法

  1. 用Java代码加密示例明文,记录基准结果。
  2. 运行修正后的Go代码,对比加密后的Base64字符串是否与Java结果一致。
  3. 若仍不一致,确认两端使用的是同一银联公钥证书。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:45:32