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

Golang RSA-OAEP加密后Java解密报BadPaddingException问题排查

解决Golang RSA-OAEP加密后Java解密报BadPaddingException的问题

我之前也踩过Golang RSA-OAEP加密、Java解密出现BadPaddingException: Decryption error的坑,几乎都是两端加密参数不匹配导致的——RSA-OAEP对哈希算法、掩码函数这些细节要求特别严格,差一点都不行。结合你给出的Go代码片段,咱们一步步排查:

1. 哈希算法不匹配(最常见原因)

Go标准库的rsa.EncryptOAEP如果不指定哈希函数,默认用的是SHA-1,但很多Java代码会默认用SHA-256或者其他算法,这直接会导致padding校验失败。

对应检查点:

  • 看你的Go代码里EncryptOAEP的第一个参数:
    • 如果是rsa.EncryptOAEP(sha1.New(), ...),那Java端必须同步用SHA-1作为哈希算法
    • 如果是sha256.New(),Java端也要改成SHA-256

示例Java代码(匹配SHA-1的情况):

import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.security.PrivateKey;
import java.security.spec.MGF1ParameterSpec;

// 初始化Cipher时必须明确指定OAEP的参数
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
OAEPParameterSpec spec = new OAEPParameterSpec(
    "SHA-1", 
    "MGF1", 
    new MGF1ParameterSpec("SHA-1"), // MGF1的哈希算法要和主哈希一致
    PSource.PSpecified.DEFAULT
);
cipher.init(Cipher.DECRYPT_MODE, yourPrivateKey, spec);
byte[] decrypted = cipher.doFinal(encryptedBytes);

2. MGF1掩码函数的参数不一致

RSA-OAEP依赖MGF1(掩码生成函数),它的哈希算法必须和主加密哈希算法完全一致。Go里EncryptOAEP会自动用和第一个参数相同的哈希作为MGF1的哈希,但Java如果不显式指定,可能会用不同的算法(比如有些环境默认MGF1用SHA-1,即使主哈希是SHA-256)。

解决方法:

不管用哪种哈希,Java端都要显式指定MGF1的哈希算法,和Go端保持一致。比如Go用SHA-256时:

// Go代码示例
hash := sha256.New()
ciphertext, err := rsa.EncryptOAEP(hash, rand.Reader, rsaPublicKey, []byte(yourPlaintext), nil)

对应的Java代码:

OAEPParameterSpec spec = new OAEPParameterSpec(
    "SHA-256", 
    "MGF1", 
    new MGF1ParameterSpec("SHA-256"), 
    PSource.PSpecified.DEFAULT
);

3. 明文长度超出限制

RSA-OAEP对明文长度有严格限制:

最大明文长度 = 密钥长度(字节) - 2*哈希长度(字节) - 2

比如2048位RSA密钥(256字节),用SHA-1(20字节)的话,最大明文长度是256 - 2*20 -2 = 214字节。如果Go加密的明文超过这个长度,要么加密时出错,要么被截断,导致Java解密时padding校验失败。

解决方法:

  • 检查你要加密的字符串长度,超过限制的话,不要直接用RSA加密大文本,改用对称加密+RSA加密对称密钥的方案(比如AES加密文本,然后用RSA加密AES密钥)。

4. 公钥解析是否正确

你的Go代码里用x509.ParseCertificate解析证书获取公钥,但忽略了解析错误。要确保:

  • 证书里的公钥确实是RSA类型(不是EC或其他)
  • 解析过程没有报错(把cert, _ = x509.ParseCertificate(block.Bytes)改成带错误检查的代码,比如:
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
    log.Fatalf("Failed to parse certificate: %v", err)
}
rsaPublicKey, ok := cert.PublicKey.(*rsa.PublicKey)
if !ok {
    log.Fatal("Public key is not RSA")
}

5. OAEP的Label参数是否一致

Go的EncryptOAEP最后一个参数是label(可选),如果你的代码里传了非nil的值,Java端解密时必须用完全相同的label。你的代码里是nil,对应Java端用PSource.PSpecified.DEFAULT(空label)就没问题,这点要确认。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:13:02