Asynchronous OpenPGP cryptography methods are available in sub classes with the Async suffix. The main two classes of the library that offer the most commonly used PGP functionality are PGPLibAsync and KeyStoreAsync.
Async examples in this chapter
- Encrypting
- Decrypting
- Signing
- Clear text signing
- Verifying signed content
- Signing and encrypting
- Decrypting and verifying (Signed and encrypted content)
Encrypting
The PGPLibAsync class extending DidiSoft.Pgp.PGPLib includes methods with the Async sufix. Here is how to perform OpenPGP file encryption:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using DidiSoft.Pgp; class EncryptFileAsync { public async void Demo() { // create an instance of the library PGPLibAsync pgp = new PGPLibAsync(); // is the output ASCII or binary bool asciiArmor = true; await pgp.EncryptFileAsync(@"DataFiles\INPUT.txt", @"DataFiles\public.key", @"DataFiles\OUTPUT.pgp", asciiArmor); } } |
Decrypting
Asynchronous decrypting is done by invoking the methods ending with Async:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System; using DidiSoft.Pgp; class DecryptFileAsync { public async void Demo() { // initialize the library PGPLibAsync pgp = new PGPLibAsync(); string inputFileLocation = @"DataFiles\OUTPUT.pgp"; string privateKeyLocation = @"DataFiles\private.key"; string privateKeyPassword = "changeit"; string decryptedOutput = @"DataFiles\OUTPUT.txt"; string originalFileName = await pgp.DecryptFileAsync(inputFileLocation, privateKeyLocation, privateKeyPassword, decryptedOutput); Console.WriteLine("File decrypted to :" + decryptedOutput); Console.WriteLine("The original file name of the decrypted file was :" + originalFileName); } } |
Signing
OpenPGP signed format is created asynchronously with the methods PGPLibAsync.SignXAsync:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using System; using DidiSoft.Pgp; class SignFileAsync { public async void Demo() { // create an instance of the library PGPLibAsync pgp = new PGPLibAsync(); // should output be binary (false) or ASCII armored (true) bool asciiArmor = true; await pgp.SignFileAsync(@"DataFiles\INPUT.txt", @"DataFiles\private.key", "changeit", @"DataFiles\OUTPUTs.pgp", asciiArmor); } } |
Clear text signing
Clear text signatures are produced asynchronously with the methods PGPLibAsync.ClearSignXAsync:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System; using DidiSoft.Pgp; class CleartextSignFileAsync { public async void Demo() { // create an instance of the library PGPLibAsync pgp = new PGPLibAsync(); string privateKeyPassword = "changeit"; // clear text sign await pgp.ClearSignFileAsync(@"DataFiles\INPUT.txt", @"DataFiles\private.key", privateKeyPassword, HashAlgorithm.SHA256, @"DataFiles\OUTPUT.sig.txt"); } } |
Verifying signed content
The async methods that verify pgp digital signatures work with both signed and clear text signed messages.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | using System; using DidiSoft.Pgp; using DidiSoft.Pgp.Exceptions; class VerifyDemoAsync { public async void Demo() { // create an instance of the library PGPLibAsync pgp = new PGPLibAsync(); // verify SignatureCheckResult signatureCheck = SignatureCheckResult.NoSignatureFound; try { signatureCheck = await pgp.VerifyFileAsync(@"DataFiles\OUTPUTs.pgp", @"DataFiles\public.key", @"DataFiles\OUTPUT.txt"); } catch (PGPException e) { if (e is NonPGPDataException) { Console.WriteLine("The input file is not an OpenPGP archive or is corrupted"); } else if (e is WrongPublicKeyException) { Console.WriteLine("The supplied public key is not an OpenPGP public key or is corrupted"); } else if (e is FileIsEncryptedException) { Console.WriteLine("The input file is OpenPGP encrypted. You have to use Decrypt or DecryptAndVerify!"); } else { Console.WriteLine(e.Message); } } if (signatureCheck == SignatureCheckResult.SignatureVerified) { Console.WriteLine("Signature OK"); } else if (signatureCheck == SignatureCheckResult.SignatureBroken) { Console.WriteLine("Signature of the message is either broken or forged"); } else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching) { Console.WriteLine("The provided public key doesn't match the signature"); } else if (signatureCheck == SignatureCheckResult.NoSignatureFound) { Console.WriteLine("This message is not digitally signed"); } } } |
Signing and encrypting
Producing one pass signed and encrypted content asynchronously is no different from the standard synchronous methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using System; using DidiSoft.Pgp; class SignAndEncryptFileAsync { public async void Demo() { // create an instance of the library PGPLibAsync pgp = new PGPLibAsync(); // specify should the output be ASCII or binary bool asciiArmor = false; await pgp.SignAndEncryptFileAsync(@"DataFiles\INPUT.txt", @"DataFiles\private.key", "changeit", @"DataFiles\public.key", @"DataFiles\OUTPUTse.pgp", asciiArmor); } } |
Decrypting and verifying (Signed and encrypted content)
Decryption and verification are done in a single step with PGPLibAsync.DecryptAndVerifyXAsync:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | using System; using DidiSoft.Pgp; using DidiSoft.Pgp.Exceptions; namespace PGPLibExampleCS.Async { class DecryptAndVerifyFileAsync { public async void Demo() { // create an instance of the library PGPLibAsync pgp = new PGPLibAsync(); // private key to be used for decryption String privateKeyFile = @"DataFiles\private.key"; String privateKeyPassword = "changeit"; // public key of the sender, to be used for signature verficitaion String senderPublicKeyFile = @"DataFiles\public.key"; SignatureCheckResult signatureCheck = SignatureCheckResult.NoSignatureFound; try { signatureCheck = await pgp.DecryptAndVerifyFileAsync(@"DataFiles\OUTPUTse.pgp", privateKeyFile, privateKeyPassword, senderPublicKeyFile, @"DataFiles\OUTPUT.txt"); } catch (PGPException e) { if (e is NonPGPDataException) { Console.WriteLine("The input file is not an OpenPGP archive or is corrupted"); } else if (e is WrongPublicKeyException) { Console.WriteLine("The supplied public key is not an OpenPGP public key or is corrupted"); } else if (e is WrongPrivateKeyException) { // The message cannot be decrypted with this private key // or the supplied private key is not an OpenPGP private key or is corrupted Console.WriteLine(e.Message); } else if (e is WrongPasswordException) { Console.WriteLine("The password for the private key is incorrect"); } else if (e is FileIsPBEEncryptedException) { Console.WriteLine("The input file is password encrypted."); Console.WriteLine("You have to use DecryptAndVeifyFilePBE or DecryptAndVerifyStreamPBE"); } else if (e is IntegrityCheckException) { Console.WriteLine("The encrypted data is corrupted"); } else { Console.WriteLine(e.Message); } } if (signatureCheck == SignatureCheckResult.SignatureVerified) { Console.WriteLine("Signature OK"); } else if (signatureCheck == SignatureCheckResult.SignatureBroken) { Console.WriteLine("Signature of the message is either broken or forged"); } else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching) { Console.WriteLine("The provided public key doesn't match the signature"); } else if (signatureCheck == SignatureCheckResult.NoSignatureFound) { Console.WriteLine("This message is not digitally signed"); } } } } |
Summary
This chapter illustrated async operations with PGPLibAsync class (a sub class of DidiSoft.Pgp.PGPLib). Currently the asynchronous methods are implemented internally by wrapping in Task.Run invocations the ordinal synchronous methods. In an upcoming release they will be updated with low level asynchronous implementation with support for progress feedback and cancellation tokens.