Analyzing pgp data in C# and VB.NET

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:

Algorithm for inspecting an arbitrary OpenPGP file

Back to Top

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

Back to Top

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

Back to Top

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