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 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
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 |
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 |
3. Verify a String message using the 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 |
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 |
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 |
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 |
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 |
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 ids 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 |