Search code examples
c#bouncycastlepgp

How to sign public PGP key with Bouncy Castle in C#


I want to create web of trust support in my application, allowing my users to use their private keys, to sign other user's public keys - Using C# and Bouncy Castle.

I've got most things figured out, such as creating PGP keys, submitting them to key servers using HTTP REST, encrypting MIME messages and cryptographically signing them (using MimeKit) - But the one remaining hurdle, is to figure out some piece of code that can use my private key, to sign for another person's public key, using Bouncy Castle.

Since the documentation for BC is horrendous, figuring out these parts, have previously proven close to impossible ...

For the record, I'm using GnuPG as my storage for keys.

If anybody wants to look at my code so far for what I have done, feel free to check it out here.

I am probably not supposed to ask this here, but I'd also love it if some BC gurus out there could have a general look at my code so far, and check if I've made a fool of myself with the stuff I've done so far ...


Solution

  • Found the answer after a lot of trial and error, here it is ...

    private static byte[] SignPublicKey(
        PgpSecretKey secretKey,
        string password,
        PgpPublicKey keyToBeSigned,
        bool isCertain)
    {
        // Extracting private key, and getting ready to create a signature.
        PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey (password.ToCharArray());
        PgpSignatureGenerator sGen = new PgpSignatureGenerator (secretKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
        sGen.InitSign (isCertain ? PgpSignature.PositiveCertification : PgpSignature.CasualCertification, pgpPrivKey);
    
        // Creating a stream to wrap the results of operation.
        Stream os = new MemoryStream();
        BcpgOutputStream bOut = new BcpgOutputStream (os);
        sGen.GenerateOnePassVersion (false).Encode (bOut);
    
        // Creating a generator.
        PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
        PgpSignatureSubpacketVector packetVector = spGen.Generate();
        sGen.SetHashedSubpackets (packetVector);
        bOut.Flush();
    
        // Returning the signed public key.
        return PgpPublicKey.AddCertification (keyToBeSigned, sGen.Generate()).GetEncoded();
    }