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
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 |
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 |
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 |