Decrypting PGP data with C# and VB.NET

This chapter illustrates OpenPGP decryption with C# and VB.NET examples.

In order to decrypt an OpenPGP encrypted file, we need the private key corresponding to the public key(s) it was encrypted with. Note that an OpenPGP archive may contain multiple files, although the most common scenario is only one file in an OpenPGP archive.

Another possibility is if the OpenPGP file was encrypted with a password and we shall use the same password to decrypt it.

List of examples

Decrypting a file

1. With private key located in a file
2. With private key located in a KeyStore

Decrypting a file that may contain multiple files into a folder

3. With private key located in a file
4. With private key located in a KeyStore

Decrypting a String message

5. With private key located in a file
6. With private key located in a KeyStore

Decrypting a Stream

7. With private key supplied as a stream
8. With private key located in a KeyStore

Decrypting password encrypted content

9. Decrypting password encrypted data

Appendix

A. Exception handling

1. Decrypting a file with a private key located in a file

This example demonstrates OpenPGP file decryption with a private key stored in a file. The private key password is also needed, in order the key to be used.

The method DecryptFile returns the original file name of the extracted file.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptDemo
{
 public void Demo()
 {
  // initialize the library
  PGPLib pgp = new PGPLib();
 
  string inputFileLocation = @"c:\INPUT.pgp";
  string privateKeyLocation = @"c:\private_key.asc";
  string privateKeyPassword = "key password";
  string outputFile = @"c:\Output.txt";
 
  // decrypt and obtain the original file name
  // of the decrypted file
  string originalFileName =
              pgp.DecryptFile(inputFileLocation,
                          privateKeyLocation,
                          privateKeyPassword,
                          outputFile);
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptDemo
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  Dim inputFileLocation As String = "c:\INPUT.pgp"
  Dim privateKeyLocation As String = "c:\private_key.asc"
  Dim outputFile As String = "c:\Output.txt"
 
  ' decrypt and obtain the original file name
  Dim originalFileName As String
  originalFileName = pgp.DecryptFile(inputFileLocation , _
                                     privateKeyLocation , _
                                     "key password", _
                                      outputFile)
 End Sub
End Class

2. Decrypting a file with a private key located in a KeyStore

This example is equivalent to the above one, except that the private decryption key is stored in a KeyStore object. Keeping our private keys in a KeyStore gives us extra layer of security.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptDemo
{
 public void Demo()
 {
  // initialize the library
  PGPLib pgp = new PGPLib();
 
  // initialize the KeyStore
  KeyStore keyStore = KeyStore.OpenFile(@"c:\key.store", "my keystore password");
 
  string inputFileLocation = @"c:\INPUT.pgp";
  string privateKeyPassword = "key password";
  string outputFile = @"c:\Output.txt";
 
  string privateKeyPassword = "changeit";
 
  //decrypt and obtain the original file name
  string originalFileName = pgp.DecryptFile(inputFileLocation,
                                                        keyStore,
                                                        privateKeyPassword,
                                                        outputFile);
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptDemo
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  ' initialize the KeyStore
  Dim keysStore As KeyStore = KeyStore.OpenFile("c:\key.store", "my keystore password")
 
  Dim inputFileLocation As String = "c:\INPUT.pgp"
  Dim privateKeyPassword As String = "key password"
  Dim outputFile As String = "c:\Output.txt"
 
  ' decrypt and obtain the original file name
  Dim originalFileName As String = _
               pgp.DecryptFile(inputFileLocation , _
                               keysStore, _
                               privateKeyPassword, _
                               outputFile)
 End Sub
End Class

3. Decrypting OpenPGP file contents to a folder when our private key is located in a file

This example demonstrates how to decrypt the contents of an OpenPGP archive into a folder. The DecryptTo method returns array of full file paths of the decrypted file(s).

This method supports decrypting multi-file OpenPGP archives, which is a feature supported by PGP Desktop version 9 and newer.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptDemo
{
 public void Demo()
 {
  // initialize the library
  PGPLib pgp = new PGPLib();
 
  string inputFileLocation = @"c:\INPUT.pgp";
  string privateKeyLocation = @"c:\private_key.asc";
  string privateKeyPassword = "key password";
  string outputFolder = @"c:\Output";
 
  // decrypt and return array with full file paths
  // of the extracted file(s)
  string[] decryptedFileNames =
    pgp.DecryptTo(inputFileLocation,
		  privateKeyLocation,
		  privateKeyPassword,
		  outputFolder);
 
  // print the full path of the decrypted file(s)
  foreach (string filename in decryptedFileNames)
  {
    System.Console.WriteLine(filename);
  }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptDemo
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  Dim inputFileLocation As String = "c:\INPUT.pgp"
  Dim privateKeyLocation As String = "c:\private_key.asc"
  Dim outputFolder As String = "c:\Output"
 
  ' decrypt and return array with full file paths
  ' of the extracted file(s)
  Dim decryptedFileNames As String() = _
    pgp.DecryptTo(inputFileLocation, _
		privateKeyLocation, _
		"key password", _
		outputFolder)
 
  ' print the full path of the decrypted file(s)
  For Each filename As String In decryptedFileNames
      System.Console.WriteLine(filename)
  Next
 End Sub
End Class

(This method was introduced in version 1.6.2)

4. Decrypting OpenPGP file contents to a folder when our private key is located in a KeyStore

This example is equivalent to the above one, except that we have placed our private key in a KeyStore.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptToDemo
{
 public void Demo()
 {
  // initialize the library
  PGPLib pgp = new PGPLib();
 
  // initialize the KeyStore
  KeyStore keyStore = KeyStore.OpenFile(@"c:\key.store", "my keystore password");
 
  string inputFileLocation = @"c:\INPUT.pgp";
  string privateKeyPassword = "key password";
  string outputFolder = @"c:\Output";
 
  // decrypt and return array with full file paths
  // of the extracted file(s)
  string[] decryptedFileNames =
    pgp.DecryptTo(inputFileLocation,
		  keyStore,
	          privateKeyPassword,
		  outputFolder);
 
  // print the full path of the decrypted file(s)
  foreach (string filename in decryptedFileNames)
  {
    System.Console.WriteLine(filename);
  }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptToDemo
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  ' initialize the KeyStore
  Dim keysStore As KeyStore = KeyStore.OpenFile("c:\key.store", "my keystore password")
 
  Dim inputFileLocation As String = "c:\INPUT.pgp"
  Dim outputFolder As String = "c:\Output"
 
  ' decrypt and return array with full file paths
  ' of the extracted file(s)
  Dim decryptedFileNames As String() = _
	  pgp.DecryptTo(inputFileLocation, _
			keysStore, _
			"key password", _
			outputFolder)
 
  ' print the full path of the decrypted file(s)
  For Each filename As String In decryptedFileNames
      System.Console.WriteLine(filename)
  Next
 End Sub
End Class

(This method was introduced in version 1.6.2)

5. Decrypting a String with a private key located in a file

Sometimes we may receive a string message and in that case it is easier to decrypt it directly instead of writing it to a file before that. The example below shows how to achieve this:

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
class DecryptString {
 public String Decrypt(String encryptedString)
 {
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   String plainString =
     pgp.DecryptString(encryptedString,
		       new FileInfo(@"DataFiles\private.key"),
                       "private key password");
 
   return plainString;
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Class DecryptString
 Public Shared Function Decrypt(ByVal encryptedString _
                               As String) As String
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  Dim plainString As String = _
    pgp.DecryptString(encryptedString, _
 		New FileInfo("DataFiles\private.key"), _
		"private key password")
 
  Return plainString
 End Function
End Class

6. Decrypting a String with a decryption key located in a KeyStore

The example below shows how to decrypt a string message when our private decryption key is stored in a KeyStore object.

C# example

using System;
using DidiSoft.Pgp;
using DidiSoft.Pgp.Exceptions;
 
class KeyStoreDecryptString
{
 public void Demo()
 {
  // initialize the key store
  KeyStore ks = new KeyStore(@"c:\key.store", "keystore password");
 
  try {
        // create an instance of the library
        PGPLib pgp = new PGPLib();
 
	// obtain encrypted string
	string encryptedString = ...
 
	string plainText = pgp.DecryptString(encryptedString, ks);
  }
  catch (WrongPrivateKeyException)
  {
	Console.WriteLine("No suitable dercyption key was found" +
                          " in this key store.");
  }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
Imports DidiSoft.Pgp.Exceptions
 
Class KeyStoreDecryptString
 Public Sub Demo()
  ' initialize the key store
  Dim ks As KeyStore = KeyStore.OpenFile("c:\key.store", "my keystore password")
 
  Try
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' obtain enrypted string message
   Dim encryptedString As String = ...
 
   Dim plainText As String = pgp.DecryptString(encryptedString, ks)
  Catch generatedExceptionName As WrongPrivateKeyException
   Console.WriteLine("No suitable decryption key was found " + _
                     "in this key store.")
  End Try
 End Sub
End Class

7. Decrypting PGP encrypted input stream with a private key supplied as a stream

An important point in this example is that the decrypted data is written down on an output Stream. If afterwards we wish to read the decrypted data, we have to create a stream for reading from the decrypted stream (for example we can supply a MemoryStream for the decryptedStream parameter and after decrypting create a new MemoryStream(decryptedStream.ToArray()).

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
public class DecryptStreamDemo
{
 public Stream Decrypt()
 {
   // initialize the library
   PGPLib pgp = new PGPLib();
 
   MemoryStream decryptedOutput = new MemoryStream();
 
   //
   // Although here the data stream and the private key are file streams
   //  they can be any kind of stream
   //
   using (Stream dataFileStream = File.OpenRead(@"DataFiles\INPUT.pgp"))
   using (Stream privateKeyStream = File.OpenRead(@"DataFiles\private.key"))
   {
      string privateKeyPassword = "changeit";
 
      string originalFileName =
        pgp.DecryptStream(dataFileStream,
                          privateKeyStream,
                          privateKeyPassword,
                          decryptedOutput);
 
      Console.WriteLine("The original file name of the decrypted data was :" 
                        + originalFileName);
 
      //
      // Because the decryptedOutput stream Position is at the end of the stream,
      // we have to reinitialize it in order to be able to read it afterwards
      //
      decryptedOutput = new MemoryStream(decryptedOutput.ToArray());
      return decryptedOutput;
  }
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Public Class DecryptStreamDemo
 Public Function Decrypt() As Stream
   ' initialize the library
   Dim pgp As New PGPLib()
 
   Dim decryptedOutput As New MemoryStream()
 
   '
   ' Although here the data stream and the private key are file streams
   '  they can be any kind of stream
   '
   Using dataFileStream As Stream = File.OpenRead("DataFiles\INPUT.pgp")
    Using privateKeyStream As Stream = File.OpenRead("DataFiles\private.key")
        Dim privateKeyPassword As String = "changeit"
 
        Dim originalFileName As String = _
                pgp.DecryptStream(dataFileStream, _
                                  privateKeyStream, privateKeyPassword, decryptedOutput)
 
        Console.WriteLine("The original file name of the decrypted data was :" + originalFileName)
 
        '
        ' Because the decryptedOutput stream Position is at the end of the stream,
        ' we have to reinitialize it in order to be able to read it afterwards
        '
        decryptedOutput = New MemoryStream(decryptedOutput.ToArray())
        Return decryptedOutput
   End Using
  End Using
 End Function
End Class

8. Decrypting PGP encrypted input stream with a private key located in a KeyStore

This example is equivalent to the above one, except that the private key is located in a KeyStore object.

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
public class KeyStoreDecryptStream
{
 public void Demo()
 {
   // initialize the library
   PGPLib pgp = new PGPLib();
 
   // initialize the key store
   KeyStore kStore = KeyStore.OpenFile(@"c:\key.store", "my keystore password");
 
   MemoryStream decryptedOutput = new MemoryStream();
 
   //
   // Although here the data stream and the private key are file streams
   //  they can be any kind of stream
   //
   using (Stream dataFileStream = File.OpenRead(@"DataFiles\INPUT.pgp"))
   {
	string privateKeyPassword = "changeit";
 
	string originalFileName =
	  pgp.DecryptStream(dataFileStream,
			  kStore,
			  privateKeyPassword,
			  decryptedOutput);
 
	Console.WriteLine("The original file name of the decrypted data was :"
							+ originalFileName);
 
	//
	// Because the decryptedOutput stream Position is at the end of the stream,
	// we have to reinitialize it in order to be able to read it afterwards
	//
	decryptedOutput = new MemoryStream(decryptedOutput.ToArray());
   }
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Public Class KeyStoreDecryptStream
 Public Sub Demo()
   ' initialize the library
   Dim pgp As New PGPLib()
 
   ' initialize the key store
   Dim kStore As KeyStore = KeyStore.OpenFile("c:\key.store", "my keystore password")
 
   Dim decryptedOutput As New MemoryStream()
 
   '
   ' Although here the data stream and the private key are file streams
   '  they can be any kind of stream
   '
   Using dataFileStream As Stream = File.OpenRead("DataFiles\INPUT.pgp")
    Dim privateKeyPassword As String = "changeit"
 
    Dim originalFileName As String = _
                  pgp.DecryptStream(dataFileStream, _
				kStore, _
				privateKeyPassword, _
				decryptedOutput)
 
    Console.WriteLine("The original file name of the decrypted data was :" + originalFileName)
 
    '
    ' Because the decryptedOutput stream Position is at the end of the stream,
    ' we have to reinitialize it in order to be able to read it afterwards
    '
    decryptedOutput = New MemoryStream(decryptedOutput.   
  End Using
 End Sub
End Class

9. Decrypting password encrypted OpenPGP data

In this example we specify the file name where the decrypted data will be extracted.

If the PGP encrypted file contains multiple files we can call the method PGPLib.DecryptPBEInFolder instead.

C# example

using System;
using DidiSoft.Pgp;
 
public class DecryptPBEDemo
{
 public void Demo()
 {
	// initialize the library
	PGPLib pgp = new PGPLib();
 
	string inputFileLocation = @"c:\INPUT.pgp";
	string password = "password";
	string decryptedOutput = @"c:\OUTPUT.txt";
 
	// decrypt and obtain the original file name
	string originalFileName =
	  pgp.DecryptFilePBE(inputFileLocation,
					  password,
					  decryptedOutput);
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class DecryptPBEDemo
 Public Sub Demo()
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' decrypt and obtain the original file name
   Dim originalFileName As String
   originalFileName = _
	  pgp.DecryptFilePBE("c:\INPUT.pgp", _
				"password", _
				"c:\OUTPUT.txt")
 End Sub
End Class

Appendix A. Exception Handling

All decryption methods throw two general exceptions: System.IO.IOException and DidiSoft.Pgp.PGPException.

For OpenPGP specific exception cases we can try to check does the thrown exception belong to one of the defined exception sub classes from the DidiSoft.Pgp.Exceptions namespace. The example below illustrates the sub classes that we may expect.

C# example

using System;
using DidiSoft.Pgp;
using DidiSoft.Pgp.Exceptions;
 
public class ExceptionHandlingDemo
{
 public void Demo()
 {
  // initialize the library
  PGPLib pgp = new PGPLib();
 
  try 
  {
	pgp.Decrypt ...
  } catch (IOException e) {
  // error reading input or writing output
  } catch (PGPException e) {
   if (e is NonPGPDataException)
   {
   // the passed encrypted input is not a valid OpenPGP archive
   }
   else if (e is IntegrityCheckException)
   {
   // the passed encrypted input is corrupted
   }
   else if (e is FileIsPBEEncryptedException)
   {
   // the passed encrypted input is encrypted with a password,
   // but we try to decrypt it with a private key
   }
   else if (e is WrongPrivateKeyException)
   {
   // the encrypted input was encrypted with a different private key
   // than the provided one
   }
   else if (e is WrongPasswordException)
   {
   // the password for the provided private key is wrong
   }
   else
   {
   // general decryption error not among the above ones 
   }
  }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
Imports DidiSoft.Pgp.Exceptions
 
Class ExceptionHandlingDemo
 Public Sub Demo()
  ' initialize the library
  Dim pgp As New PGPLib()
 
  Try
	pgp.Decrypt ...
  Catch e As IOException
  ' error reading input or writing output
  Catch e As PGPException
   If TypeOf e Is NonPGPDataException Then
   ' the passed encrypted input is not a valid OpenPGP archive
   ElseIf TypeOf e Is IntegrityCheckException Then
   ' the passed encrypted input is corrupted
   ElseIf TypeOf e Is FileIsPBEEncryptedException Then
   ' the passed encrypted input is encrypted with a password,
   ' but we try to decrypt it with a private key
   ElseIf TypeOf e Is WrongPrivateKeyException Then
   ' the encrypted input was encrypted with a different private key
   ' than the provided one
   ElseIf TypeOf e Is WrongPasswordException Then
   ' the password for the provided private key is wrong
   Else
   ' general decryption error not among the above ones 
   End If
  End Try
 End Sub
End Class

Summary

This chapter presented examples illustrating decryption of OpenPGP encrypted files. Decryption of files, string messages and stream content were shown.

From here you can continue to the chapters for verification of OpenPGP signed data and decrypting and verifying one pass signed archives.

You may also be interested in analyzing the contents of an OpenPGP archive before actually extracting it.

Methods used:

PGPLib.DecryptFile Decripts a .pgp file that contains one encrypted file
PGPLib.DecryptTo Decripts a .pgp file that contains one or multiple files
PGPLib.DecryptStream Decripts an OpenPGP encrypted Stream
PGPLib.DecryptString Decripts an OpenPGP encrypted String message
PGPLib.DecryptFilePBE Decripts a .pgp file that was encrypted with a password