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

如何使用BouncyCastle验证OpenPGP签名(C#场景)

解决PGP签名验证始终返回False的问题

看起来你在这里踩了一个常见的坑:把PGP格式的签名和公钥当成普通RSA密钥/签名来处理了。PGP有自己的封装规范,不能直接用.NET原生的RSACryptoServiceProvider来验证,必须借助BouncyCastle的PGP专用API完成整个流程。

核心问题分析

  1. 你尝试直接把PGP公钥解析成RsaKeyParameters,但PGP公钥是包含在**公钥环(PGP Public Key Ring)**中的复合格式,不是单独的RSA密钥PEM,所以会出现"公钥块不匹配"的错误。
  2. PGP签名不是原始的RSA签名值,它内嵌了哈希算法标识、签名者信息等元数据,直接用VerifyHash验证自然会失败。

正确的解决方案步骤

我们需要用BouncyCastle的PGP相关类来完成完整的验证流程:

  1. 从公钥字符串加载PGP公钥环,提取有效公钥
  2. 确保待验证数据的编码和签名生成时一致(文档指定ASCII)
  3. 解析PGP签名字节数组为PGP签名对象
  4. 使用BouncyCastle的验证器绑定公钥并完成验证

完整代码示例

using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using System.IO;
using System.Text;
using System.Linq;

private bool VerifyPgpSignature(string data, byte[] signatureBytes, string publicKeyString)
{
    // 1. 加载PGP公钥环并提取有效公钥
    PgpPublicKey publicKey = null;
    using (var keyStream = new MemoryStream(Encoding.ASCII.GetBytes(publicKeyString)))
    {
        var pubKeyRing = new PgpPublicKeyRing(PgpUtilities.GetDecoderStream(keyStream));
        // 获取第一个可用的加密/签名公钥(若有多个,可根据签名者ID匹配)
        publicKey = pubKeyRing.GetPublicKeys()
            .Cast<PgpPublicKey>()
            .First(k => k.IsEncryptionKey || k.IsSigningKey);
    }

    if (publicKey == null)
        throw new InvalidOperationException("未找到有效的PGP公钥");

    // 2. 准备待验证的数据流
    var dataStream = new MemoryStream(Encoding.ASCII.GetBytes(data));

    // 3. 解析PGP签名
    var signatureStream = new MemoryStream(signatureBytes);
    var pgpSignature = new PgpSignature(PgpUtilities.GetDecoderStream(signatureStream));

    // 4. 初始化验证器,绑定公钥
    pgpSignature.InitVerify(publicKey);

    // 5. 写入数据完成验证计算
    int readByte;
    while ((readByte = dataStream.ReadByte()) >= 0)
    {
        pgpSignature.Update((byte)readByte);
    }

    // 6. 返回最终验证结果
    return pgpSignature.Verify();
}

关键注意事项

  • 公钥加载方式:必须用PgpPublicKeyRing解析PGP公钥,不能用普通的PemReader(后者仅用于单独的RSA/ECDSA密钥PEM)。
  • 编码一致性:严格匹配签名生成时的编码(文档指定ASCII,若实际是UTF-8需替换),编码不一致会导致哈希值不匹配。
  • 签名格式检查:确认你获取的sig字节数组是标准PGP签名格式,若为Base64编码需先解码为字节数组再传入。

如果仍有问题,可以排查:

  • 公钥是否正确加载(可打印公钥指纹/ID与文档对比)
  • 待验证数据是否和签名生成时的原始数据完全一致(包括换行符、空格等细节)
  • 签名是否被篡改或格式损坏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:31:29