In the common scenario, we usually have an upfront agreement with our partners what kind of OpenPGP data will be exchanged.
But sometimes we may have to deal with unknown OpenPGP archives and we do not know are they signed only, encrypted with a key, etc. Or we may just want to list the contents of an OpenPGP file without decrypting it.
In this chapter, we are going to explain and demonstrate the functionality provided by DidiSoft OpenPGP Library for .NET that can be of help in the above situations.
Examples in this chapter
Analyzing an arbitrary OpenPGP archive
Listing the contents of an OpenPGP archive
DidiSoft.Pgp.Inspect namespace
The namespace DidiSoft.Pgp.Inspect contains a special class PGPInspectLib that provides methods for analyzing the internals of OpenPGP files.
Below is a flowchart that summarizes the algorithm for analyzing an arbitrary OpenPGP archive:
Below you can see the above flowchart in sample C# and VB.NET code
C# example
using System; using System.IO; using DidiSoft.Pgp; using DidiSoft.Pgp.Exceptions; using DidiSoft.Pgp.Inspect; class AnalyzeOpenPGPFile { public void Analyze(FileInfo file) { // create an instance of the library PGPLib pgp = new PGPLib(); // create an instance of the inspection library PGPInspectLib inspect = new PGPInspectLib(); // check is this a signed only file if (inspect.IsSignedOnly(file)) { long[] signingKeyIds = inspect.ListSigningKeyIds(file); foreach (long keyId in signingKeyIds) { Console.WriteLine("Signed with Key ID : " + KeyPairInformation.KeyIdToHex(keyId)); } //pgp.VerifyFile ... } // check is this a key encrypted file else if (inspect.IsPublicKeyEncrypted(file)) { // List encryption Key ID's long[] encryptionKeyIds = inspect.ListEncryptionKeyIds(file); foreach (long keyId in encryptionKeyIds) { Console.WriteLine("Encrypted with Key ID : " + KeyPairInformation.KeyIdToHex(keyId)); } // List signing Key ID's long[] signingKeyIds = inspect.ListSigningKeyIds(file, new FileInfo(@"c:\private_key.asc"), "key password"); foreach (long keyId in signingKeyIds) { Console.WriteLine("Signed with Key ID : " + KeyPairInformation.KeyIdToHex(keyId)); } if (signingKeyIds.Length == 0) { // This is an encrypted only file // pgp.DecryptFile ... } else { // This is a one pass signed and encrypted file // pgp.DecryptAndVerifyFile ... } } // check is this a password encrypted file else if (inspect.IsPBEEncrypted(file)) { // pgp.DecryptFilePBE ... } else { // Maybe this is only a literal data file, // try to decrypt with an arbitrary private key // pgp.DecryptFile ... } } } |
VB.NET example
Imports System Imports System.IO Imports DidiSoft.Pgp Imports DidiSoft.Pgp.Exceptions Imports DidiSoft.Pgp.Inspect Class AnalyzeOpenPGPFile Public Sub Analyze(ByVal file As FileInfo) ' create an instance of the library Dim pgp As New PGPLib() ' create an instance of the inspection library Dim inspect As New PGPInspectLib() ' check is this a signed only file If inspect.IsSignedOnly(file) Then Dim signingKeyIds As Long() = inspect.ListSigningKeyIds(file) For Each keyId As Long In signingKeyIds Console.WriteLine("Signed with Key ID : " + _ KeyPairInformation.KeyIdToHex(keyId)) ' pgp.VerifyFile ... Next ' check is this a key encrypted file ElseIf inspect.IsPublicKeyEncrypted(file) Then ' List encryption Key ID's Dim encryptionKeyIds As Long() = inspect.ListEncryptionKeyIds(file) For Each keyId As Long In encryptionKeyIds Console.WriteLine("Encrypted with Key ID : " + _ KeyPairInformation.KeyIdToHex(keyId)) Next ' List signing Key ID's Dim signingKeyIds As Long() = _ inspect.ListSigningKeyIds(file, _ New FileInfo("c:\private_key.asc"), _ "key password") For Each keyId As Long In signingKeyIds Console.WriteLine("Signed with Key ID : " + _ KeyPairInformation.KeyIdToHex(keyId)) Next If signingKeyIds.Length = 0 Then ' This is an encrypted only file ' pgp.DecryptFile Else ' This is a one pass signed and encrypted file ' pgp.DecryptAndVerifyFile ... End If ' check is this a password encrypted file ElseIf inspect.IsPBEEncrypted(file) Then ' pgp.DecryptFilePBE ... Else ' Maybe this is only a literal data file, ' try to decrypt with an arbitrary private key ' pgp.DecryptFile ... End If End Sub End Class |
List the contents of an OpenPGP archive
There may be situations when we want to know the contents of an OpenPGP archive before actually extracting it. The example below shows how to list the contents of an OpenPGP archive without decrypting it.
C# example
using System; using DidiSoft.Pgp; using DidiSoft.Pgp.Inspect; public class InspectEncryptedFile { public void Demo() { // // Inspect the content of an encrypted file without decrypting it // String privateKey = @"c:\private_key.asc"; String privateKeyPassword = "key password"; String encryptedFile = @"c:\encrypted.pgp"; PGPInspectLib inspectLib = new PGPInspectLib(); ContentItem[] files = inspectLib.ListOpenPgpFile(encryptedFile, _ privateKey, _ privateKeyPassword); Console.WriteLine(encryptedFile + " contains:"); foreach (ContentItem file in files) { Console.Write(file.FileName); Console.Write(file.IsDirectory ? "[dir]" : "[file]"); Console.WriteLine(file.ModificationTime); } } } |
VB.NET example
Imports System Imports DidiSoft.Pgp Imports DidiSoft.Pgp.Inspect Public Class InspectEncryptedFile Public Sub Demo() ' ' Inspect the content of an encrypted file without decrypting it ' Dim privateKey As String = "c:\private_key.asc" Dim privateKeyPassword As String = "key password" Dim encryptedFile As String = "c:\encrypted.pgp" Dim inspectLib As New PGPInspectLib() Dim files As ContentItem() = inspectLib.ListOpenPgpFile(encryptedFile, _ privateKey, _ privateKeyPassword) Console.WriteLine(encryptedFile + " contains:") For Each file As ContentItem In files Console.Write(file.FileName) Console.Write(IIf(file.IsDirectory, "[dir]", "[file]")) Console.WriteLine(file.ModificationTime) Next End Sub End Class |
Summary
In this chapter, we have demonstrated how to analyze an unknown OpenPGP archive. The class that provides OpenPGP inspection functionality is PGPInspectLib located in the DidiSoft.Pgp.Inspect namespace.
List of methods used:
PGPInspectLib.IsSignedOnly | Checks is a file/stream an OpenPGP signed only archive |
PGPInspectLib.IsPublicKeyEncrypted | Checks is a file/stream an OpenPGP key encrypted archive |
PGPInspectLib.IsPBEEncrypted | Checks is a file/stream an OpenPGP password encrypted archive |
PGPInspectLib.ListSigningKeyIds | Returns the key ID’s of the keys that have signed an OpenPGP archive |
PGPInspectLib.ListEncryptionKeyIds | Returns the key ID’s of the keys that have encrypted an OpenPGP archive |
PGPInspectLib.ListOpenPgpFile | Lists the contents of an OpenPGP archive |