Decrypt and verify pgp data in C# and VB.NET

When we receive OpenPGP one pass signed and encrypted message we can simply decrypt it or both decrypt the data and verify the authenticity of the sender in a single step.

This tutorial refers to version 1.7.12 or newer of the library. The tutorial for older versions is available here.

The examples below show how to perform both decryption and verification with DidiSoft OpenPGP Library for .NET:

Decrypt and verify file

1. with keys located in files | Async
2. with keys located in a KeyStore | Async

Decrypt and verify a String message

5. with keys located in files | Async
6. with keys located in a KeyStore | Async

Decrypt and verify a Stream message

5. with keys located in files | Async
6. with keys located in a KeyStore | Async

Decrypt and verify a file that may contain multiple files inside

3. with keys located in files
4. with keys located in a KeyStore

Decrypt and verify password encrypted file

7. with a public key located in a file
8. with a public key located in a KeyStore

Appendix

A. Exception handling

1. Decrypt and verify file with keys located in files

This example demonstrates OpenPGP decryption and verification of an OpenPGP one pass signed and encrypted file.
We use the public key of the sender to verify the source of this signed file. Our own private key is used for decryption.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptAndVerify
{
 public void Demo()
 {
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    SignatureCheckResult signatureCheck = 
         pgp.DecryptAndVerifyFile(@"C:\Test\OUTPUT.pgp",
                                  @"C:\Test\my_private_key.asc",
                                  "private key password",
                                  @"C:\Test\sender_public_key.asc",
                                  @"C:\Test\INPUT.txt");
   if (signatureCheck == SignatureCheckResult.SignatureVerified)
   {
	   Console.WriteLine("Signare OK");
   }
   else if (signatureCheck == SignatureCheckResult.SignatureBroken)
   {
	   Console.WriteLine("Signare 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");
   }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptAndVerify
 Public Sub Demo()
   ' create an instance of the library   
   Dim pgp As New PGPLib()
 
   Dim signatureCheck As SignatureCheckResult = _
       pgp.DecryptAndVerifyFile("C:\Test\OUTPUT.pgp", _
				"C:\Test\my_private_key.asc", _
				"private key password", _
				"C:\Test\sender_public_key.asc", _
				"C:\Test\INPUT.txt")
   If signatureCheck = SignatureCheckResult.SignatureVerified Then
	Console.WriteLine("Signare OK")
   ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
	Console.WriteLine("Signare of the message is either broken or forged")
   ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
	Console.WriteLine("The provided public key(s) doesn't match the signature")
   ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
	Console.WriteLine("This message is not digitally signed")
   End If
 End Sub
End Class

1-A. Async decrypt and verify a file

The asynchronous version of the DecryptAndVerifyFile is PGPLibAsync.DecryptAndVerifyFileAsync. Here the same set of parameters, including the public key of the message sender and our private key apply, but in addition a CancellationToken can also be provided as last optional parameter.

The example code below, contains code that handles all possible exceptions and all possible signature check outcomes. You can erase a lot of this logic, if your use case, doesn’t require so much low level details.

In case we don’t want to extract the data, just verify the signature, we can use one of the PGPLib.VerifySignedAndEncryptedFileAsync methods.

using System;
using System.Threading;
using System.Threading.Tasks;
using DidiSoft.Pgp;
 
public class DecryptAndVerify
{
 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";
 
  // optional parameter
  CancellationToken token = default(CancellationToken);
 
  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");
  }
 }
}

2. Decrypt and verify file with keys located in a KeyStore

In this example, the public key of the sender is used for verification and our private key is used for decryption and they both are located in a KeyStore.

C# example

using System;
using DidiSoft.Pgp;
 
public class KeyStoreDecryptAndVerifyFile
{
 public static void Demo()
 {
   // initialize the KeyStore
   KeyStore keyStore = new KeyStore(@"c:\key.store", "key store pass");
 
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   // we should provide the private decryption key password too
   String decryptionKeyPassword = "private key password";
   SignatureCheckResult signatureCheck = 
                       pgp.DecryptAndVerifyFile(@"c:\INPUT.pgp",
						keyStore,
						decryptionKeyPassword,
						@"c:\OUTPUT.txt");
   if (signatureCheck == SignatureCheckResult.SignatureVerified)
   {
	   Console.WriteLine("Signare OK");
   }
   else if (signatureCheck == SignatureCheckResult.SignatureBroken)
   {
	   Console.WriteLine("Signare 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");
   }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class KeyStoreDecryptAndVerifyFile
 Public Shared Sub Demo()
    ' initialize the KeyStore
    Dim keyStore As New KeyStore("c:\key.store", "key store pass")
 
    ' create an instance of the library
    Dim pgp As New PGPLib()
 
    ' we should provide the private decryption key password too
    Dim decryptionKeyPassword As String = "private key password"
    Dim signatureCheck As SignatureCheckResult = _
                pgp.DecryptAndVerifyFile("c:\OUTPUT.pgp", _
					  keyStore, _
					  decryptionKeyPassword, _
					  "c:\OUTPUT.txt")
    If signatureCheck = SignatureCheckResult.SignatureVerified Then
		Console.WriteLine("Signare OK")
    ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
		Console.WriteLine("Signare of the message is either broken or forged")
    ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
		Console.WriteLine("The provided public key(s) doesn't match the signature")
    ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
		Console.WriteLine("This message is not digitally signed")
    End If
 
 End Sub
End Class

2-A. Async decrypt and verify file with keys from a KeyStore

In this asynchronous decryption and verification of an OpenPGP signed and encrypted file, the decryption and the verification keys are in a KeyStore object. In this keys we don’t have to explicitly specify the decryption key, nor the public key for verification.

C# example

using System;
using System.Threading;
using System.Threading.Tasks;
using DidiSoft.Pgp;
 
public class KeyStoreDecryptAndVerifyFile
{
  public async Task Demo()
  {
	// initialize the key store
	KeyStore keyStore = new KeyStore(@"DataFiles\key.store", "changeit");
 
	// initialize the library
	PGPLibAsync pgp = new PGPLibAsync();
 
	String decryptionKeyPassword = "private key password";
 
        // optional parameter
        CancellationToken token = default(CancellationToken);
 
	SignatureCheckResult signatureCheck =
		await pgp.DecryptAndVerifyFileAsync(@"DataFiles\OUTPUT.pgp",
						keyStore,
						decryptionKeyPassword,
						@"DataFiles\OUTPUT.txt",
                                                token);
 
	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");
	}
  }
}

7. Decrypt and verify a multiple file archive with keys located in files

This sample is useful in cases when the .pgp archive contains multiple files inside. The only drawback is that this we need to invoke two methods instead of one:

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptAndVerifyMulti
{
 public void Demo()
 {
	// create an instance of the library
	PGPLib pgp = new PGPLib();
 
	// 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";
 
	string outputFolder = @"DataFiles";
 
	SignatureCheckResult signatureCheck = 
			pgp.VerifyFileWithoutExtracting(@"DataFiles\OUTPUTse.pgp",
							 privateKeyFile,
							 privateKeyPassword,
							 senderPublicKeyFile);
 
        if (signatureCheck == SignatureCheckResult.SignatureVerified)
        {
	   Console.WriteLine("Signare OK");
        }
	else if (signatureCheck == SignatureCheckResult.SignatureBroken)
	{
	   Console.WriteLine("Signare 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");
	}
 
	// decrypts the content of the PGP archive
	// and returns array with full file paths of the 
	// exytracted file(s)
	string[] decryptedFileNames =
		pgp.DecryptTo(@"DataFiles\OUTPUTse.pgp",
					privateKeyFile,
					privateKeyPassword,
					outputFolder);
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptAndVerifyMulti
 Public Sub Demo()
	' create an instance of the library
	Dim pgp As New PGPLib()
 
	' private key to be used for decryption
	Dim privateKeyFile As [String] = "DataFiles\private.key"
	Dim privateKeyPassword As [String] = "changeit"
 
	' public key of the sender, to be used for signature verficitaion
	Dim senderPublicKeyFile As [String] = "DataFiles\public.key"
 
	Dim outputFolder As String = "DataFiles"
 
	Dim signatureCheck As SignatureCheckResult = _
		pgp.VerifyFileWithoutExtracting("DataFiles\OUTPUTse.pgp", _
						privateKeyFile, _
						privateKeyPassword, _
						senderPublicKeyFile)
 
	If signatureCheck = SignatureCheckResult.SignatureVerified Then
		Console.WriteLine("Signare OK")
	ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
		Console.WriteLine("Signare of the message is either broken or forged")
	ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
		Console.WriteLine("The provided public key(s) doesn't match the signature")
	ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
		Console.WriteLine("This message is not digitally signed")
	End If
 
	' decrypts the content of the PGP archive
	' and returns array with full file paths of the 
	' exytracted file(s)
 
	Dim decryptedFileNames As String() = _
		pgp.DecryptTo("DataFiles\OUTPUTse.pgp", _
					privateKeyFile, _
					privateKeyPassword, _
					outputFolder)
 End Sub
End Class

8. Decrypt and verify multiple file archive with keys located in a KeyStore

This sample is similar to the above one, but now the public key of the sender and our decryption private key are located in a KeyStore.

C# example

using System;
using DidiSoft.Pgp;
 
public class KeyStoreDecryptAndVerifyMulti
{
 public void Demo()
 {
	// create an instance of the library
	PGPLib pgp = new PGPLib();
 
	KeyStore keyStore = new KeyStore(@"DataFiles\key.store", "changeit");
 
	String privateKeyPassword = "changeit";
 
	string outputFolder = @"DataFiles";
 
	SignatureCheckResult signatureCheck = 
			pgp.VerifyFileWithoutExtracting(@"DataFiles\OUTPUTse.pgp",
									 keyStore,
									 privateKeyPassword);
 
	if (signatureCheck == SignatureCheckResult.SignatureVerified)
	{
	   Console.WriteLine("Signare OK");
	}
	else if (signatureCheck == SignatureCheckResult.SignatureBroken)
	{
	   Console.WriteLine("Signare 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");
	}
 
	// decrypts the content of the PGP archive
	// and returns array with full file paths of the 
	// exytracted file(s)
	string[] decryptedFileNames =
		pgp.DecryptTo(@"DataFiles\OUTPUTse.pgp",
					keyStore,
					privateKeyPassword,
					outputFolder);
	}
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class KeyStoreDecryptAndVerifyMulti
 Public Sub Demo()
	' create an instance of the library
	Dim pgp As New PGPLib()
 
	Dim keyStore As New KeyStore("DataFiles\key.store", "changeit")
 
	Dim privateKeyPassword As [String] = "changeit"
 
	Dim outputFolder As String = "DataFiles"
 
	Dim signatureCheck As SignatureCheckResult = _
		pgp.VerifyFileWithoutExtracting("DataFiles\OUTPUTse.pgp", _
										keyStore, _
										privateKeyPassword)
 
	If signatureCheck = SignatureCheckResult.SignatureVerified Then
		Console.WriteLine("Signare OK")
	ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
		Console.WriteLine("Signare of the message is either broken or forged")
	ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
		Console.WriteLine("The provided public key(s) doesn't match the signature")
	ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
		Console.WriteLine("This message is not digitally signed")
	End If
 
	' decrypts the content of the PGP archive
	' and returns array with full file paths of the 
	' exytracted file(s)
	Dim decryptedFileNames As String() = _
		pgp.DecryptTo("DataFiles\OUTPUTse.pgp", _
					keyStore, _
					privateKeyPassword, _
					outputFolder)
 End Sub
End Class

3. Decrypt and verify a String message with keys located in files

If we have an encrypted and signed String message we can decrypt and verify it directly without writing it into a file beforehand as you can see from the example code below:

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
class DecryptAndVerifyString
{
 public void Demo()
 {
   // obtain encrypted and signed message
   String signedAndEncryptedMessage = ...
 
   String plainTextExtracted;
 
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   // decrypt and verify
   SignatureCheckResult signatureCheck = 
       pgp.DecryptAndVerifyString(signedAndEncryptedMessage,
				@"c:\my_private_key.asc",
				"private key password",
				@"c:\sender_public_key.asc",
				out plainTextExtracted);
   // print the results
   if (signatureCheck == SignatureCheckResult.SignatureVerified)
   {
	   Console.WriteLine("Signare OK");
   }
   else if (signatureCheck == SignatureCheckResult.SignatureBroken)
   {
	   Console.WriteLine("Signare 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");
   }
 
   Console.WriteLine("Extracted message: " + plainTextExtracted);
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Class DecryptAndVerifyString
 Public Sub Demo()
   ' obtain encrypted and signed message
   Dim signedAndEncryptedMessage As String = ...
 
   Dim plainTextExtracted As String
 
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' decrypt and verify
   Dim signatureCheck As SignatureCheckResult = _
           pgp.DecryptAndVerifyString(signedAndEncryptedMessage, _
                                     "c:\private.key", _
                                     "private key password", _
                                     "c:\public.key", _
                                     plainTextExtracted)
   ' print the results
   If signatureCheck = SignatureCheckResult.SignatureVerified Then
	Console.WriteLine("Signare OK")
   ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
	Console.WriteLine("Signare of the message is either broken or forged")
   ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
	Console.WriteLine("The provided public key(s) doesn't match the signature")
   ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
	Console.WriteLine("This message is not digitally signed")
   End If
 
  Console.WriteLine("Extracted message: " + plainTextExtracted)
 End Sub
End Class

3-A. Async Decrypt and verify a String message

We can also asynchronously decrypt and verify a signed and encrypted String message with the method PGPLibAsync.DecryptAndVerifyStringAsync.

A specific point here is that the signature check result and the decrypted message are returned in a of type Tuple<SignatureCheckResult, String>:

using System;
using System.Threading;
using System.Threading.Tasks;
using DidiSoft.Pgp;
 
class DecryptAndVerifyString
{
  public async Task Demo()
  {
	// obtain encrypted and signed message
	String signedAndEncryptedMessage = SignAndEncryptString.Demo();
 
	// create instance of the library
	PGPLibAsync pgp = new PGPLibAsync();
 
	// optional parameter
	CancellationToken token = default(CancellationToken);
 
	// although we supply here the keys as file locations 
        // they can also be passed as ASCII armor serialzed strings
	Tuple<SignatureCheckResult, string> result = 
                await pgp.DecryptAndVerifyStringAsync(signedAndEncryptedMessage,
							 @"DataFiles\private.key",
							 "private key password",
							 @"DataFiles\public.key",
							 token);
 
	SignatureCheckResult signatureCheck = result.Item1;
	string plainTextExtracted = result.Item2;
 
	// print results
	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");
	}
 
	Console.WriteLine("Extracted message: " + plainTextExtracted);
  }
}

4. Decrypt and verify string message with keys located in a KeyStore

This example shows how to decrypt and verify a signed and encrypted String message with keys stored in a KeyStore

C# example

using System;
using DidiSoft.Pgp;
 
class KeyStoreDecryptAndVerifyString
{
 public static void Demo()
 {
    // obtain an OpenPGP signed and enrypted message
    String signedAndEncryptedString = ...
 
    String privateKeyDecryptionPassword = "private key password";
 
    // Extract the message and check the validity of the signature
    String plainText;
 
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    // initialize the key store
    KeyStore ks = new KeyStore(@"c:\key.store", "key store password");
 
    SignatureCheckResult signatureCheck = 
           pgp.DecryptAndVerifyString(signedAndEncryptedString,
				     ks,
				     privateKeyDecryptionPassword,
				     out plainText);
 
    // Print the results
    Console.WriteLine("Extracted plain text message is " + plainText);
 
    if (signatureCheck == SignatureCheckResult.SignatureVerified)
    {
	   Console.WriteLine("Signare OK");
    }
    else if (signatureCheck == SignatureCheckResult.SignatureBroken)
    {
	   Console.WriteLine("Signare 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");
    }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Class KeyStoreDecryptAndVerifyString
 Public Shared Sub Demo()
   ' obtain an OpenPGP signed and enrypted message
   Dim signedAndEncryptedString As String = ...
 
   Dim privateKeyDecryptionPassword As String = "private key password"
 
   ' Extract the message and check the validity of the signature
   Dim plainText As String
 
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' initialize the key store
   Dim ks As New KeyStore("c:\key.store", "key store password")
 
   Dim signatureCheck As SignatureCheckResult = _
           pgp.DecryptAndVerifyString(signedAndEncryptedString, _
                                      ks, _
                                      privateKeyDecryptionPassword, _
                                      plainText)
 
   ' Print the results
   Console.WriteLine("Extracted plain text message is " + plainText)
 
  If signatureCheck = SignatureCheckResult.SignatureVerified Then
	Console.WriteLine("Signare OK")
  ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
	Console.WriteLine("Signare of the message is either broken or forged")
  ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
	Console.WriteLine("The provided public key(s) doesn't match the signature")
  ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
	Console.WriteLine("This message is not digitally signed")
  End If
 End Sub
End Class

4-A. Async decrypt and verify string message with keys from a KeyStore

In the overloaded version of the method PGPLibAsync.DecryptAndVerifyStringAsync that expects the keys from a KeyStore object, we just have to provide the password of our private key.

The signature check result and the decrypted string message are returned as Tuple<SignatureCheckResult, String>:

using System;
using DidiSoft.Pgp;
 
class KeyStoreDecryptAndVerifyString
{
  public async Task Demo()
  {
	// obtain an OpenPGP signed and enrypted message
	String signedAndEncryptedString = SignAndEncryptString.Demo();
 
	String privateKeyPassword = "private key password";
 
	// initialize the library
	PGPLibAsync pgp = new PGPLibAsync();
 
	// initialize the key store
	KeyStore ks = new KeyStore(@"DataFiles\key.store", "changeit");
 
	// optional parameter
	CancellationToken token = default(CancellationToken);
 
	Tuple<SignatureCheckResult, string> result = 
            await pgp.DecryptAndVerifyStringAsync(signedAndEncryptedString,
						ks,
						privateKeyPassword,
						token);
 
	// signature check result
	SignatureCheckResult signatureCheck = result.Item1;
	// Extracted message 
	string plainText = result.Item2;
 
	// Print the results
	Console.WriteLine("Extracted plain text message is " + plainText);
 
	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");
	}
  }
}

5. Decrypt and verify a Stream

If we have Stream containing OpenPGP encrypted and signed data, we can decrypt and verify it directly with one of the PGPLib.DecryptAndVerifyStream methods.
Or if we want just to verify the integrity of the data, without extracting it, we can use one of the PGPLib.VerifyStreamWithoutExtracting methods.

In the example code below, we set the output Stream Position to 0 just to remind you that if you want to read the decrypted data afterwards, the Stream.Position will be at its end.

using System;
using System.IO;
using DidiSoft.Pgp;
 
public class DecryptAndVerifyStream
{
public void Demo()
{ 
	// create an instance of the library
	PGPLib pgp = new PGPLib();
 
	// OpenPGP signed and encrypted data
	using (Stream dataStream = File.OpenRead(@"DataFiles\OUTPUTse.pgp"))
	// public key of the sender, to be used for signature verification
	using (Stream senderPublicKeyStream = File.OpenRead(@"DataFiles\public.key"))
	// private key to be used for decryption
	using (Stream privateKeyStream = File.OpenRead(@"DataFiles\private.key"))
	{                
		String privateKeyPassword = "changeit";
 
		// The output can be an arbitrary subclass of System.IO.Stream
		MemoryStream outputStream = new MemoryStream();
		SignatureCheckResult signatureCheck = pgp.DecryptAndVerifyStream(dataStream,
													 privateKeyStream,
													 privateKeyPassword,
													 senderPublicKeyStream,
													 outputStream);
		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");
		}
 
		// we must reinitialize the output in order to be able to read from it
		outputStream.Position = 0;
	}
}
<a name="DecryptStreamAsync"></a>
<h2>5-A. Async Decrypt and verify a Stream</h2>
We can also asynchronously decrypt and verify an <a href="/net-openpgp/examples/openpgp-sign-and-encrypt-in-net/#SignStreamAsync">OpenPGP signed and encrypted Stream</a> with the method <b>PGPLibAsync.DecryptAndVerifyStreamAsync</b>.
 
The public key of the person or organization that signed the data must be provided for the signature verification and our private key for the data decryption.
 
<pre lang="csharp">using System;
using System.Threading;
using System.Threading.Tasks;
using DidiSoft.Pgp;
 
class DecryptAndVerifyStreamAsync
{
 public async Task Demo()
 {
	// create an instance of the library
	PGPLibAsync pgp = new PGPLibAsync();
 
	using (Stream dataStream = File.OpenRead(@"DataFiles\OUTPUTse.pgp"))
 
	// public key of the sender, to be used for signature verification
	using (Stream senderPublicKeyStream = File.OpenRead(@"DataFiles\public.key"))
 
	// private key to be used for decryption
	using (Stream privateKeyStream = File.OpenRead(@"DataFiles\private.key"))
	{
		String privateKeyPassword = "changeit";
 
		// optional parameter
		CancellationToken token = default(CancellationToken);
 
		// The output can be an arbitrary subclass of System.IO.Stream
		MemoryStream outputStream = new MemoryStream();
		SignatureCheckResult signatureCheck = await pgp.DecryptAndVerifyStreamAsync(dataStream,
													 privateKeyStream,
													 privateKeyPassword,
													 senderPublicKeyStream,
													 outputStream,
													 token);
		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");
		}
 
		// ... output position is at its end 
		// we must set it to 0 in order to be able to read from it                
	}
 }
}

6. Decrypt and verify Stream with keys from a KeyStore

This example shows how to decrypt and verify a signed and encrypted Stream with keys stored in a KeyStore
Signature verification only, can be done with the PGPLib.VerifyStream methods.


using System;
using System.IO;
using DidiSoft.Pgp;
 
public class DecryptAndVerifyStream
{
 public static void Demo()
 {
	// initialize the library
	PGPLib pgp = new PGPLib();
 
	// initialize the key store that contains the public key of the sender
	// and the private key (usually our own) that will be used for decryption
	KeyStore keyStore = new KeyStore(@"DataFiles\key.store", "changeit");
 
	// password of the private key that will be used for decryption
	String decryptionKeyPassword = "private key password";
 
	// The output can be an arbitrary subclass of System.IO.Stream
	MemoryStream outputStream = new MemoryStream();
 
	using (Stream encryptedStream = File.OpenRead(@"DataFiles\OUTPUT.pgp")) 
	{
		SignatureCheckResult signatureCheck = 
			pgp.DecryptAndVerifyStream(encryptedStream,
						keyStore,
						decryptionKeyPassword,
						outputStream);
 
		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");
		}
	}
}

6-A. Async decrypt and verify Stream with keys from a KeyStore

The method PGPLibAsync.DecryptAndVerifyStreamAsync can also use key from a KeyStore object, we just have to provide the password of our private key.

using System;
using System.IO;
using DidiSoft.Pgp;
 
class DecryptAndVerifyStreamAsyncKS
{
public async Task Demo()
{
	// initialize the library
	PGPLibAsync pgp = new PGPLibAsync();
 
	// initialize the key store that contains the public key of the sender
	// and the private key (usually our own) that will be used for decryption
	KeyStore keyStore = new KeyStore(@"DataFiles\key.store", "changeit");
 
	// password of the private key that will be used for decryption
	String decryptionKeyPassword = "private key password";
 
	// The output can be an arbitrary subclass of System.IO.Stream
	MemoryStream outputStream = new MemoryStream();
 
	// optional parameter
	CancellationToken token = default(CancellationToken);
 
	using (Stream encryptedStream = File.OpenRead(@"DataFiles\OUTPUT.pgp"))
	{
		SignatureCheckResult signatureCheck =
			await pgp.DecryptAndVerifyStreamAsync(encryptedStream,
								keyStore,
								decryptionKeyPassword,
								outputStream,
								token);
 
		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");
		}
 
		// we must reinitialize the output in order to be able to read from it
		outputStream.Position = 0;
	}
}

9. Decrypt and verify a password encrypted file with a public key located in a file

This example demonstrates OpenPGP decryption and verification of an OpenPGP one pass signed and password encrypted file. We use the public key of the other party to verify the source of this signed file. The decryption password is the same as the one used for encryption.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptAndVerifyPBE
{
 public void Demo()
 {
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    SignatureCheckResult signatureCheck =
         pgp.DecryptAndVerifyFilePBE(@"C:\Test\OUTPUT.pgp",
                                  "encryption password",
                                  @"C:\Test\sender_public_key.asc",
                                  @"C:\Test\INPUT.txt");
 
   if (signatureCheck == SignatureCheckResult.SignatureVerified)
   {
	   Console.WriteLine("Signare OK");
   }
   else if (signatureCheck == SignatureCheckResult.SignatureBroken)
   {
	   Console.WriteLine("Signare 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");
   }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptAndVerifyPBE
 Public Sub Demo()
   ' create an instance of the library   
   Dim pgp As New PGPLib()
 
   Dim signatureCheck As SignatureCheckResult = _
    pgp.DecryptAndVerifyFilePBE("C:\Test\OUTPUT.pgp", _
				"encryption password", _
				"C:\Test\sender_public_key.asc", _
				"C:\Test\INPUT.txt")
 
   If signatureCheck = SignatureCheckResult.SignatureVerified Then
	Console.WriteLine("Signare OK")
   ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
	Console.WriteLine("Signare of the message is either broken or forged")
   ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
	Console.WriteLine("The provided public key(s) doesn't match the signature")
   ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
	Console.WriteLine("This message is not digitally signed")
   End If
 End Sub
End Class

10. Decrypt and verify password encrypted file when the public key is located in a KeyStore

In this example, the public key of the sender used for verification is located in a KeyStore and the same password used for encryption is used for decryption.

C# example

using System;
using DidiSoft.Pgp;
 
public class KeyStoreDecryptAndVerifyFile
{
 public static void Demo()
 {
   // initialize the KeyStore
   KeyStore keyStore = new KeyStore(@"c:\key.store", "key store pass");
 
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   // we should provide the private decryption key password too
   String decryptionPassword = "encryption password";
   SignatureCheckResult signatureCheck = 
                    pgp.DecryptAndVerifyFilePBE(@"c:\INPUT.pgp",
						keyStore,
						decryptionPassword,
						@"c:\OUTPUT.txt");
 
   if (signatureCheck == SignatureCheckResult.SignatureVerified)
   {
	   Console.WriteLine("Signare OK");
   }
   else if (signatureCheck == SignatureCheckResult.SignatureBroken)
   {
	   Console.WriteLine("Signare 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");
   }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class KeyStoreDecryptAndVerifyFile
 Public Shared Sub Demo()
    ' initialize the KeyStore
    Dim keyStore As New KeyStore("c:\key.store", "key store pass")
 
    ' create an instance of the library
    Dim pgp As New PGPLib()
 
    ' we should provide the decryption password 
    Dim decryptionPassword As String = "encryption password"
    Dim signatureCheck As SignatureCheckResult = _
                pgp.DecryptAndVerifyFile("c:\OUTPUT.pgp", _
					  keyStore, _
					  decryptionPassword, _
					  "c:\OUTPUT.txt")
 
    If signatureCheck = SignatureCheckResult.SignatureVerified Then
	Console.WriteLine("Signare OK")
    ElseIf signatureCheck = SignatureCheckResult.SignatureBroken Then
	Console.WriteLine("Signare of the message is either broken or forged")
    ElseIf signatureCheck = SignatureCheckResult.PublicKeyNotMatching Then
	Console.WriteLine("The provided public key(s) doesn't match the signature")
    ElseIf signatureCheck = SignatureCheckResult.NoSignatureFound Then
	Console.WriteLine("This message is not digitally signed")
    End If
 End Sub
End Class

Back to Top

Appendix A. Exception Handling

The sample code below follows the proposed general exception handling and illustrates the exceptions subclasses of DidiSoft.Pgp.PGPException that we may expect when decrypting and verifying OpenPGP data in one pass.

C# example

using System;
using DidiSoft.Pgp;
using DidiSoft.Pgp.Exceptions;
 
public class DecryptAndVerify
{
 public void Demo()
 {
  // create an instance of the library
  PGPLib pgp = new PGPLib();
 
  try
  {	
   SignatureCheckResult signatureCheck = pgp.DecryptAndVerify ...
  }
  catch (PGPException e)
  {
   if (e is NonPGPDataException)
   {
	// The input data is not an OpenPGP archive or is corrupted
   }
   else if (e is WrongPublicKeyException)
   {
	// 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)
   {
	// The password for the private key is incorrect
   }
   else if (e is FileIsPBEEncryptedException)
   {
	// The input file is password encrypted
	// We have to use DecryptAndVeifyFilePBE or DecryptAndVerifyStreamPBE
   }
   else if (e is IntegrityCheckException)
   {
	// The encrypted data is corrupted
   }
   else
   { // other OpenPGP error
	Console.WriteLine(e.Message);
   }
  }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
Imports DidiSoft.Pgp.Exceptions
 
Public Class DecryptAndVerify
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  Try
	Dim signatureCheck As SignatureCheckResult = pgp.DecryptAndVerify ...
  Catch e As PGPException
   If TypeOf e Is NonPGPDataException Then
	' The input file is not an OpenPGP archive or is corrupted
   ElseIf TypeOf e Is WrongPublicKeyException Then
	' The supplied public key is not an OpenPGP public key or is corrupted
   ElseIf TypeOf e Is WrongPrivateKeyException Then
	' 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)
   ElseIf TypeOf e Is WrongPasswordException Then
	' The password for the private key is incorrect
   ElseIf TypeOf e Is FileIsPBEEncryptedException Then
	' The input file is password encrypted.
	' You have to use DecryptAndVeifyFilePBE or DecryptAndVerifyStreamPBE
   ElseIf TypeOf e Is IntegrityCheckException Then
	' The encrypted data is corrupted
   Else
	Console.WriteLine(e.Message)
   End If
  End Try
 End Sub
End Class

Back to Top

Summary

In this chapter, we have demonstrated how to decrypt and verify in one step a single pass signed and encrypted OpenPGP data.

In case we don’t want to extract the data, just verify the signature, we can use one of the PGPLib.VerifySignedAndEncrypted… methods.

You may also be interested in analyzing an OpenPGP archive and checking the encryption and signing Key ids before performing decryption and signature verification.

List of methods used:

PGPLib.DecryptAndVerifyFile Decrypts and verifies the digital signature of an OpenPGP encrypted file
PGPLib.DecryptAndVerifyString Decrypts and verifies the digital signature of an OpenPGP encrypted String message
PGPLib.DecryptAndVerifyStream Decrypts and verifies the digital signature of an OpenPGP encrypted Stream
PGPLib.DecryptAndVerifyFilePBE Decrypts and verifies the digital signature of an OpenPGP password encrypted file
PGPLibAsync.DecryptAndVerifyFileAsync Async Decrypts and verifies the digital signature of an OpenPGP encrypted file
PGPLibAsync.DecryptAndVerifyStringAsync Async Decrypts and verifies the digital signature of an OpenPGP encrypted String message
PGPLibAsync.DecryptAndVerifyStreamAsync Async Decrypts and verifies the digital signature of an OpenPGP encrypted Stream