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

C#中使用Bouncy Castle实现PGP一键签名加密示例求助

使用Bouncy Castle实现文件签名+加密

依赖准备

先安装对应的NuGet包:

Install-Package Org.BouncyCastle
Install-Package Org.BouncyCastle.Bcpg

核心实现代码

签名需要发送方的私钥(带密码),加密需要接收方的公钥,以下是一次完成签名+加密的完整实现:

using System.IO;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;

public static class PgpFileHandler
{
    /// <summary>
    /// 对目标文件执行签名+加密操作
    /// </summary>
    /// <param name="inputPath">待处理文件路径</param>
    /// <param name="outputPath">生成的签名加密文件路径</param>
    /// <param name="senderPrivKeyPath">发送方PGP私钥文件路径</param>
    /// <param name="privKeyPassword">私钥解锁密码</param>
    /// <param name="recipientPubKeyPath">接收方PGP公钥文件路径</param>
    public static void SignAndEncrypt(string inputPath, string outputPath, string senderPrivKeyPath, string privKeyPassword, string recipientPubKeyPath)
    {
        using var inputStream = File.OpenRead(inputPath);
        using var outputStream = File.Create(outputPath);

        // 加载接收方加密公钥
        var recipientPubKey = LoadPublicKey(recipientPubKeyPath);
        // 加载发送方签名私钥
        var senderPrivKey = LoadPrivateKey(senderPrivKeyPath, privKeyPassword);

        // 初始化加密生成器,采用CAST-5对称加密算法
        var encryptGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, new SecureRandom());
        encryptGenerator.AddMethod(recipientPubKey);

        // 创建加密输出流
        var encryptedStream = encryptGenerator.Open(outputStream, new byte[4096]);

        // 初始化签名生成器,采用SHA-256哈希算法
        var signatureGenerator = new PgpSignatureGenerator(senderPrivKey.PublicKey.Algorithm, HashAlgorithmTag.Sha256);
        signatureGenerator.InitSign(PgpSignature.BinaryDocument, senderPrivKey);

        // 设置签名者用户信息
        foreach (var userId in senderPrivKey.PublicKey.GetUserIds())
        {
            var subpacketGen = new PgpSignatureSubpacketGenerator();
            subpacketGen.SetSignerUserId(false, userId.ToString());
            signatureGenerator.SetHashedSubpackets(subpacketGen.Generate());
            break; // 取第一个用户ID即可
        }

        // 创建带签名的输出流(如果不需要ASCII装甲,可替换为BufferedStream)
        var signedStream = new ArmoredOutputStream(encryptedStream);
        // 写入一次性签名头
        signatureGenerator.GenerateOnePassVersion(false).Encode(signedStream);

        // 读取文件内容,同时更新签名并写入加密流
        var buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            signedStream.Write(buffer, 0, bytesRead);
            signatureGenerator.Update(buffer, 0, bytesRead);
        }

        // 写入最终签名
        signatureGenerator.Generate().Encode(signedStream);

        // 依次关闭流
        signedStream.Close();
        encryptedStream.Close();
    }

    /// <summary>
    /// 加载PGP公钥
    /// </summary>
    private static PgpPublicKey LoadPublicKey(string pubKeyPath)
    {
        using var keyStream = File.OpenRead(pubKeyPath);
        var pubRingBundle = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyStream));
        foreach (PgpPublicKeyRing ring in pubRingBundle.GetKeyRings())
        {
            foreach (PgpPublicKey key in ring.GetPublicKeys())
            {
                if (key.IsEncryptionKey)
                {
                    return key;
                }
            }
        }
        throw new InvalidDataException("未找到可用的加密公钥");
    }

    /// <summary>
    /// 加载PGP私钥
    /// </summary>
    private static PgpPrivateKey LoadPrivateKey(string privKeyPath, string password)
    {
        using var keyStream = File.OpenRead(privKeyPath);
        var privRingBundle = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(keyStream));
        foreach (PgpSecretKeyRing ring in privRingBundle.GetKeyRings())
        {
            foreach (PgpSecretKey key in ring.GetSecretKeys())
            {
                if (key.IsSigningKey)
                {
                    return key.ExtractPrivateKey(password.ToCharArray());
                }
            }
        }
        throw new InvalidDataException("未找到可用的签名私钥");
    }
}

使用示例

// 调用示例
PgpFileHandler.SignAndEncrypt(
    inputPath: @"D:\docs\raw_file.pdf",
    outputPath: @"D:\docs\signed_encrypted_file.pgp",
    senderPrivKeyPath: @"D:\keys\my_private_key.asc",
    privKeyPassword: "my_secure_password",
    recipientPubKeyPath: @"D:\keys\recipient_public_key.asc"
);

注意事项

  • 确保私钥、公钥文件为标准PGP格式(通常是.asc或.gpg后缀)。
  • 如果不需要生成ASCII装甲格式的文件,可将ArmoredOutputStream替换为BufferedStream。
  • 签名私钥需妥善保管,泄露后可能导致签名被伪造。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 15:31:10