Search code examples
c#console-applicationbouncycastleencryptionpgp

Exception on decrypting file using BouncyCastle PGP


I was trying to decrypt this sample file given by the client, using a class called PgpDecrypt. But when the code comes to this line:

Stream clear = pbe.GetDataStream(privKey);

it returns an error: exception decrypting secret key

Here's my decryption code:

PgpDecrypt test = new PgpDecrypt(string.Concat(pathh, "TestDecryptionFile"),
                                             string.Concat(pathh, "mypgpprivatekey.key"),
                                             "mypassphrase",
                                             @"d:/test/",
                                             string.Concat(pathh, "clientpublickey.key"));

FileStream fs = File.Open(string.Concat(pathh, "TestDecryptionFile"), FileMode.Open);
test.Decrypt(fs, @"d:\test\");

I am using BouncyCastle as my third party library for .NET.

Any idea to solve this would be a great help. Thanks in advance!


Solution

  • If you're following the BouncyCastle classes PGPEncrypt, PGPDecrypt and PGPEncryptionKeys...

    Under the PGPEncryptionKeys class, add this method:

    /// <summary>
    /// Return the last key we can use to decrypt.
    /// Note: A file can contain multiple keys (stored in "key rings")
    /// </summary>
    private PgpSecretKey GetLastSecretKey(PgpSecretKeyRingBundle secretKeyRingBundle)
    {
        return (from PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings()
                select kRing.GetSecretKeys().Cast<PgpSecretKey>()
                                                .LastOrDefault(k => k.IsSigningKey))
                                                .LastOrDefault(key => key != null);
    }
    

    still inside the PgpEncryptionKeys class, make sure the ReadSecretKey method looks like this:

    private PgpSecretKey ReadSecretKey(string privateKeyPath, bool toEncrypt)
    {
        using (Stream keyIn = File.OpenRead(privateKeyPath))
        using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
        {
            PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
            PgpSecretKey foundKey = toEncrypt ? GetFirstSecretKey(secretKeyRingBundle) : GetLastSecretKey(secretKeyRingBundle);
    
            if (foundKey != null)
                return foundKey;
        }
        throw new ArgumentException("Can't find signing key in key ring.");
    }
    

    ^_^