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

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.