Verify pgp signed data in .NET

When we receive a signed or clear text signed OpenPGP data, we can both verify that it came from the sender we expect it and extract the original message at the same time. For the verification we need the public key of the sender. Of course we can ignore completely the digital signature and extract the data with a simple decryption.

The examples below demonstrate how to verify signed data with OpenPGP Library for .NET. It refers to version 1.7.12 and above. For previous versions of the library please refer to the old tutorial or check the Upgrade notes.

Verify a signed or clear text signed file

1. with a sender’s public key located in a file
2. with a sender’s public key located in a KeyStore

Verify a signed or clear text signed String message

4. with a sender’s public key located in a file
3. with a sender’s public key located in a KeyStore

Verify a signed or clear text signed Stream

5. with a sender’s public key as Stream
6. with a sender’s public key located in a KeyStore

Appendix

A. Exception handling

1. Verifying a signed or clear text signed file using sender’s public key located also in a file

There is also an overloaded version of the VerifyFile method that allows just to verify the digital signature without actually extracting the data.

C# example

using System;
using DidiSoft.Pgp;
 
public class VerifyDemo
{
    public void Demo()
    {
       // create an instance of the library
       PGPLib pgp = new PGPLib();
 
       // check the signature and extract the data 
       SignatureCheckResult signatureCheck = 
           pgp.VerifyFile(@"C:\Test\INPUT.pgp",
                          @"C:\Test\public_key.asc",
                          @"C:\Test\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 VerifyDemo
    Public Sub Demo()
        ' create an instance of the library
        Dim pgp As New PGPLib()
 
        ' check the signature and extract the data 
        Dim signatureCheck As SignatureCheckResult = _
             pgp.VerifyFile("C:\Test\INPUT.pgp", _
                            "C:\Test\public_key.asc", _
                            "C:\Test\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

2. Verify a signed or clear text signed file using sender’s public key located in a KeyStore

This example is equivalent to the above one, except that the public key of the sender is located in a KeyStore object. The digital signature will be verified among all the public keys in the specified KeyStore.

C# example

using System;
using DidiSoft.Pgp;
 
class KeyStoreVerifyFile
{
 public static void Demo()
 {
	// create an instance of the library
	PGPLib pgp = new PGPLib();
 
	// initialize the KeyStore
	// If the keystore file does not exists, it is created.
	KeyStore ks = new KeyStore(@"DataFiles\key.store", "changeit");
 
	// verify OpenPGP signed or clear text signed file
	string outputFileLocation = @"c:\OUTPUT.txt";
	SignatureCheckResult signatureCheck = pgp.VerifyFile(@"c:\signed.pgp",
					                     ks,
				                             outputFileLocation);
 
	// Print the results
	Console.WriteLine("Extracted data in " + outputFileLocation);
        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 KeyStoreVerifyFile
 Public Shared Sub Demo()
	' create an instance of the library
	Dim pgp As New PGPLib()
 
	' initialize the KeyStore
	' If the keystore file does not exists, it is created.
	Dim ks As New KeyStore("DataFiles\key.store", "changeit")
 
	' verify OpenPGP signed or clear text signed file
	Dim outputFileLocation As String = "DataFiles\OUTPUT.txt"
	Dim signatureCheck As SignatureCheckResult = _
             pgp.VerifyFile("DataFiles\OUTPUT.pgp", _
                            ks, _
                            outputFileLocation)
 
	' Print the results
	Console.WriteLine("Extracted data in " + outputFileLocation)
 
	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

3. Verify a String message using sender’s public key located in a file

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
class VerifyString
{
 public static void Demo()
 {
   // obtain an OpenPGP signed message
   String signedString = SignString.Demo();
 
   // Extract the message and check the validity of the signature
   String plainText;
   PGPLib pgp = new PGPLib();
   SignatureCheckResult signatureCheck = pgp.VerifyString(signedString,
					new FileInfo(@"c\public_key.asc"),
					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 System.IO
Imports DidiSoft.Pgp
 
Class VerifyString
  Public Shared Sub Demo()
   ' obtain an OpenPGP signed message
   Dim signedString As String = SignString.Demo()
 
   ' Extract the message and check the validity of the signature
   Dim plainText As String
   Dim pgp As New PGPLib()
   Dim signatureCheck As SignatureCheckResult = _
     pgp.VerifyString(signedString, _
                      New FileInfo("c:\public_key.asc"), _
		      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

Back to Top

4. Verify a string message using sender’s public key located in a KeyStore

If we keep our OpenPGP keys in a KeyStore we should use the overloaded VerifyString method that accepts a KeyStore object:

C# example

using System;
using DidiSoft.Pgp;
 
class KeyStoreVerifyString
{
 public static void Demo()
 {
   // obtain an OpenPGP signed message
   String signedString = KeyStoreSignString.Demo();
 
   // Extract the message and check the validity of the signature
   String plainText;
   PGPLib pgp = new PGPLib();
   KeyStore ks = new KeyStore(@"DataFiles\key.store", "changeit");
   SignatureCheckResult signatureCheck = pgp.VerifyString(signedString,
 					                  ks,
					                  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 KeyStoreVerifyString
 Public Shared Sub Demo()
   ' obtain an OpenPGP signed message
   Dim signedString As String = KeyStoreSignString.Demo()
 
   ' Extract the message and check the validity of the signature
   Dim plainText As String
   Dim pgp As New PGPLib()
   Dim ks As New KeyStore("DataFiles\key.store", "changeit")
   Dim signatureCheck As SignatureCheckResult = pgp.VerifyString(signedString, ks, 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

Back to Top

5. Verify a signed or clear text signed Stream with a sender’s public key as Stream

This example shows how to verify data that is in a Stream for reading. The extracted data is stored also in a Stream.

using System;
using System.IO;
using DidiSoft.Pgp;
 
public class VerifyStream
{
 public void Demo()
 {
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   // The data and the public key can be any kind of stream
   Stream dataStream = File.OpenRead(@"c:\signed.pgp");
   Stream publicKeyStream = File.OpenRead(@"c:\public_key.asc");
 
   Stream outputStream = new MemoryStream();
 
   // verify signed or clear text signed stream
   SignatureCheckResult signatureCheck = pgp.VerifyStream(dataStream,
					publicKeyStream,
					outputStream);
 
   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");
   }
 
   // We must reinitialize the output in order to read from it later
   (outputStream as MemoryStream).Position = 0;
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Public Class VerifyStream
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  ' The data and the public key can be any kind of stream
  Dim dataStream As Stream = File.OpenRead("c:\signed.pgp")
  Dim publicKeyStream As Stream = File.OpenRead("c:\public_key.asc")
 
  Dim outputStream As Stream = New MemoryStream()
 
  ' verify signed or clear text signed stream
  Dim signatureCheck As SignatureCheckResult = _
			pgp.VerifyStream(dataStream, _
					publicKeyStream, _
					outputStream)
 
  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
 
  ' We must reinitialize the output in order to read from it later
  TryCast(outputStream, MemoryStream).Positon = 0
 End Sub
End Class

Back to Top

6. Verify a Stream when the public key of the sender is in a KeyStore

This example is equivalent to the above one, except that the sender’s public key is located in a KeyStore.

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
class KeyStoreVerifyStream
{
 public static void Demo()
 {
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   // initialize the KeyStore that contains the sender's public key
   KeyStore ks = new KeyStore(@"c:\my_key.store", "changeit");
 
   // The data and the output can be any kind of stream
   Stream dataStream = File.OpenRead(@"c:\signed.pgp");
   Stream outputStream = new MemoryStream();
 
   // verify
   string outputFileLocation = @"c:\OUTPUT.txt";
   SignatureCheckResult signatureCheck = pgp.VerifyStream(dataStream,
					 ks,
					 outputStream);
 
   // We must reinitialize the output in order to read from it later
   (outputStream as MemoryStream).Position = 0;
 
   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 System.IO
Imports DidiSoft.Pgp
 
Class KeyStoreVerifyStream
 Public Shared Sub Demo()
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' initialize the KeyStore that contains the sender's public key
   Dim ks As New KeyStore("c:\my_key.store", "changeit")
 
   ' The data and the output can be any kind of stream
   Dim dataStream As Stream = File.OpenRead("c:\signed.pgp")
   Dim outputStream As Stream = New MemoryStream()
 
   ' verify
   Dim outputFileLocation As String = "c:\OUTPUT.txt"
   Dim signatureCheck As SignatureCheckResult = pgp.VerifyStream(dataStream, ks, outputStream)
 
   ' We must reinitialize the output in order to read from it later
   TryCast(outputStream, MemoryStream).Position = 0
 
   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 exception handling code when verifying signed data shall follow the general exception strategy.

This example illustrates the expected exceptions from the methods with a Verify name prefix.

C# example

using System;
using DidiSoft.Pgp;
using DidiSoft.Pgp.Exceptions;
 
public class VerifyDemo
{
 public void Demo()
 {
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   try
   {
	SignatureCheckResult signatureCheck = pgp.Verify ...
   }
   catch (PGPException e)
   {
     if (e is NonPGPDataException)
     {
	// The input 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 FileIsEncryptedException)
     {
	// The input file is OpenPGP encrypted. 
        // You will have to use one of the Decrypt 
        // or DecryptAndVerify methods
     }
     else
     {  // general OpenPGP error
  	Console.WriteLine(e.Message);
     }
   }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
Imports DidiSoft.Pgp.Exceptions
 
Public Class VerifyDemo
 Public Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  Try
	Dim signatureCheck As SignatureCheckResult = pgp.Verify...
  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 FileIsEncryptedException Then
	' The input is OpenPGP encrypted. 
        ' You will have to use one of the Decrypt or 
        ' DecryptAndVerify methods instead
   Else 
        ' general OpenPGP error
	Console.WriteLine(e.Message)
   End If
  End Try
 End Sub
End Class

Back to Top

Summary

In this chapter we have shown how to verify an OpenPGP digital signatures and extract the signed content. The examples above apply only to signed and clear text signed data.

Additional methods exist for verification of detached signatures and one pass signed and encrypted data.

You may also be interested in analyzing OpenPGP archive and checking the signing Key ID’s before performing signature verification.

Methods used in this chapter:

PGPLib.VerifyFile Verifies an OpenPGP signed or clear text signed file
PGPLib.VerifyString Verifies an OpenPGP signed or clear text signed String message
PGPLib.VerifyStream Verifies an OpenPGP signed or clear text signed Stream