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

PGP加密代码生成的密文无法解密,报错unknown object in stream:20

PGP加密解密失败:unknown object in stream: 20 问题排查

错误根源分析

错误提示中的unknown object in stream: 20,指PGP加密流中出现了类型20的数据包(Symmetric-Key Encrypted Session Key Packet),但你的解密逻辑是按公钥加密流程处理(期望类型1的公钥加密会话密钥包),或者加密代码本身的PGP包构造逻辑存在错误。

既然在线工具能正常用同一密钥对加解密,说明密钥本身无问题,问题完全出在Groovy加密代码的实现上。

常见代码错误点及修复建议

1. 误使用对称密钥加密逻辑

如果你的代码错误调用了对称密钥加密生成器而非公钥加密生成器,就会生成类型20的数据包,导致私钥解密时无法识别:

  • 检查是否使用了PGPPublicKeyEncryptedDataGenerator(公钥加密),而非PGPSymmetricKeyEncryptedDataGenerator(对称密钥加密)
  • 确保加密时是用目标公钥加密会话密钥,而非直接用对称密钥加密消息内容

2. PGP数据包顺序错误

PGP加密流的正确构造顺序必须是:

  • 公钥加密的会话密钥包(类型1)
  • 对称加密的数据包(类型18)
    如果代码颠倒了包顺序或遗漏了必要包,解密迭代器会无法识别错误的包类型,触发该异常。

3. ASCII Armor格式不规范

在线工具输出的密文是标准ASCII Armor格式(带-----BEGIN PGP MESSAGE-----头尾标记),如果你的代码直接输出二进制流,或生成Armor时格式错误(比如缺少头尾、存在多余空白字符),也会导致解密失败:

  • 确认是否用ArmoredOutputStream包裹输出流,生成标准PGP Armor格式密文
  • 检查输出密文的头尾标记是否完整,无额外字符

4. 加密算法不匹配

检查代码中指定的对称加密算法(如AES-256)是否与密钥支持的算法一致,同时解密逻辑是否使用了相同的算法配置。若密钥仅支持CAST5但代码用了AES-256,也可能导致包解析错误。

正确的Groovy公钥加密代码示例

import org.bouncycastle.openpgp.*
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.Security
import java.security.SecureRandom

Security.addProvider(new BouncyCastleProvider())

void encryptPGPMessage(PGPPublicKey publicKey, String plainText, OutputStream outputStream) {
    // 初始化ASCII Armor输出流
    ArmoredOutputStream armoredOut = new ArmoredOutputStream(outputStream)
    
    // 初始化公钥加密会话密钥生成器
    PGPPublicKeyEncryptedDataGenerator encryptor = new PGPPublicKeyEncryptedDataGenerator()
    encryptor.addMethod(publicKey)
    
    // 生成随机对称会话密钥(AES-256)
    byte[] sessionKey = new byte[32]
    new SecureRandom().nextBytes(sessionKey)
    
    // 打开加密输出流
    OutputStream encryptedOut = encryptor.open(armoredOut, sessionKey)
    
    // 初始化压缩数据生成器
    PGPCompressedDataGenerator compressor = new PGPCompressedDataGenerator(PGPCompressedData.ZIP)
    OutputStream compressedOut = compressor.open(encryptedOut)
    
    // 初始化明文数据生成器
    PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator()
    OutputStream literalOut = literalGen.open(compressedOut, PGPLiteralData.TEXT, "", new Date(), new byte[1 << 16])
    
    // 写入明文内容
    literalOut.write(plainText.getBytes("UTF-8"))
    
    // 按顺序关闭所有流(必须严格顺序)
    literalOut.close()
    literalGen.close()
    compressedOut.close()
    compressor.close()
    encryptedOut.close()
    encryptor.close()
    armoredOut.close()
}

验证步骤

  1. 用修正后的代码重新生成密文,确认输出是标准ASCII Armor格式
  2. 用在线工具解密新密文,验证是否成功
  3. 对比原代码与示例代码的差异,重点排查加密器类型、数据包顺序、流关闭逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:10:18