One pass pgp sign and encrypt in C# and VB.NET


OpenPGP one pass signed and encrypted data is both protected and the origin of the message can be verified. The public key of the receiver is used to encrypt the message and the private (signing) key of the sender is used for creating the digital signature.

The examples below show how to sign and encrypt in one pass with DidiSoft OpenPGP Library for .NET

Sign and encrypt a file

1. with keys located in files
2. with keys located in a KeyStore

Sign and encrypt a String message

3. with keys located in files
4. with keys located in a KeyStore

Sign and encrypt a Stream

5. with keys supplied as Streams
6. with keys located in a KeyStore

Sign and encrypt a file for older OpenPGP implementations (including PGP 6.x, McAfee E-Business Server 7.x)

7. with keys located in files
8. with keys located in a KeyStore

Appendix 

A. Exception Handling

1. Sign and encrypt a file with keys located in files

This example shows how to sign and encrypt a file when our OpenPGP keys are located in files on the file system.

The parameter withIntegrityCheck must be true in order the result encrypted data to be accepted by GnuPG/gpg 2.2.8 and upper versions.

C# example

using System;
using DidiSoft.Pgp;
 
public class SignAndEncrypt
{
  public void Demo()
  {
    // create an instance of the library
    PGPLib pgp = new PGPLib();
    // is output ASCII or binary
    bool asciiArmor = true;
    // should integrity check information be added, set to true for compatibility with GnuPG 2.2.8+
    bool withIntegrityCheck = false;
    // sign and encrypt
    pgp.SignAndEncryptFile(@"C:\Test\INPUT.txt",
                           @"C:\Test\my_private_key.asc",
                           "private key password",
                           @"C:\Test\recipient_public_key.asc",
                           @"C:\Test\OUTPUT.asc",
                           asciiArmor,
                           withIntegrityCheck);
    }
}

VB.NET

Imports System
Imports DidiSoft.Pgp
 
Public Class SignAndEncrypt
  Public Sub Demo()
    ' create an instance of the library
    Dim pgp As New PGPLib()
    ' is output ASCII or binary
    Dim asciiArmor As Boolean = False
    ' should integrity check information be added, set to true for compatibility with GnuPG 2.2.8+
    Dim withIntegrityCheck As Boolean = False
    ' sign and encrypt
    pgp.SignAndEncryptFile("C:\Test\INPUT.txt", _
		           "C:\Test\my_private_key.asc", _
			   "private key password", _
			   "C:\Test\recipient_public_key.asc", _
			   "C:\Test\OUTPUT.pgp", _
			   asciiArmor, _
			   withIntegrityCheck)
  End Sub
End Class

Back to Top

2. Sign and encrypt a file with keys located in a KeyStore

In this example we sign and encrypt a file with OpenPGP keys stored in KeyStore object. We know either the User Id of the key owner or the key Id prior calling the SignAndEncryptFile method (For more KeyStore examples see the KeyTool project that ships with the library).

C# example

using System;
using DidiSoft.Pgp;
 
public class KeyStoreSignAndEncryptFile
{
  public static void Demo()
  {
    // initialize the Key store
    KeyStore keyStore = new KeyStore(@"c:\key.store",
					"keystore pass");
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    // is output ASCII or binary
    bool asciiArmor = true;
    // should integrity check information be added, set to true for compatibility with GnuPG 2.2.8+
    bool withIntegrityCheck = true;
 
    String signUserId = "support@didisoft.com";
    String signKeyPassword = "private key password";
    String encUserId = "recipient@company.com";
    // sign and encrypt
    pgp.SignAndEncryptFile(@"DataFiles\INPUT.txt",
			keyStore,
			signUserId,
			signKeyPassword,
			encUserId,
			@"DataFiles\OUTPUT.pgp",
			asciiArmor,
			withIntegrityCheck);
  }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class KeyStoreSignAndEncryptFile
 Public Shared Sub Demo()
   ' initialize the key store
   Dim keyStore As New KeyStore("DataFiles\key.store", _
				"keystore password")
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' is output ASCII or binary
   Dim asciiArmor As Boolean = True
   ' should integrity check information be added, set to true for compatibility with GnuPG 2.2.8+
   Dim withIntegrityCheck As Boolean = True
 
   Dim signUserId As String = "support@didisoft.com"
   Dim signKeyPassword As String = "private key password"
   Dim encUserId As String = "recipient@company.com"
 
   pgp.SignAndEncryptFile("DataFiles\INPUT.txt", _
			 keyStore, _
			 signUserId, _
			 signKeyPassword, _
			 encUserId, _
			"DataFiles\OUTPUT.pgp", _
                         asciiArmor, _
                         withIntegrityCheck)
 End Sub
End Class

Back to Top

3. Sign and encrypt a String with keys located in files

If we wish to sign and encrypt in one pass a string message we should use the SignAndEncryptString method:

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
class SignAndEncryptString
{
 public static String Demo()
 {
   String plainText = "Hello World";
 
   // create an instance of the library
   PGPLib pgp = new PGPLib();
 
   // sign and enrypt
   String encryptedAndSignedString =
        pgp.SignAndEncryptString(plainText,
			   new FileInfo(@"c:\private.key"),
			   "private key password",
			   new FileInfo(@"c:\public.key"));
 
   return encryptedAndSignedString;
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Class SignAndEncryptString
 Public Shared Function Demo() As String
 
   Dim plainText As String = "Hello World"
 
   ' create an instance of the library
   Dim pgp As New PGPLib()
   ' sign and enrypt
   Dim encryptedAndSignedString As String = _
             pgp.SignAndEncryptString(plainText, _
                            New FileInfo("c:\private.key"), _
			    "private key password", _
			    New FileInfo("c:\public.key"))
 
   Return encryptedAndSignedString
 End Function
End Class

Back to Top

4. Sign and encrypt a String with keys located in a KeyStore

If our keys are located in a KeyStore object and we want to sign and encrypt a string message we should use one of the overloaded versions of the SignAndEncryptString method:

C# example

using System;
using DidiSoft.Pgp;
 
class KeyStoreSignAndEncryptString
{
 public static String Demo()
 {
   // our private key User Id
   string signingKeyUserId = "support@didisoft.com";
   string signingKeyPassword = "private key password";
 
   // recipient public key User Id
   string encryptionKeyUserId = "rsa_demo@didisoft.com";
 
   // initialize the key store
   KeyStore ks = new KeyStore(@"DataFiles\key.store", "keystore password");
 
   // if this key store contains a key with the desired recipient
   // userId then sign, otherwise notify that there is no such key
   if (ks.ContainsKey(encryptionKeyUserId))
   {
     PGPLib pgp = new PGPLib();
 
     string plainText = "Hello World";
 
     string signedString =
           pgp.SignAndEncryptString(plainText, ks,
				 signingKeyUserId,
				 signingKeyPassword,
				 encryptionKeyUserId);
 
     return signedString;
   }
   else
   {
     Console.WriteLine("No key with user Id:" +
		          encryptionKeyUserId +
			  " was found in this key store.");
     return String.Empty;
   }
 }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Class KeyStoreSignAndEncryptString
 Public Shared Function Demo() As String
  ' our private key User Id
  Dim signingKeyUserId As String = "support@didisoft.com"
  Dim signingKeyPassword As String = "private key password"
 
  ' recipient public key User Id
  Dim encryptionKeyUserId As String = "rsa_demo@didisoft.com"
 
  ' initialize the key store
  Dim ks As New KeyStore("DataFiles\key.store", "keystore password")
 
  ' if this key store contains a key with the desired recipient
  ' userId then sign, otherwise notify that there is no such key
  If ks.ContainsKey(encryptionKeyUserId) Then
    Dim pgp As New PGPLib()
 
    Dim plainText As String = "Hello World"
 
    Dim signedString As String = _
    pgp.SignAndEncryptString(plainText, _
		             ks, _
		             signingKeyUserId, _
		             signingKeyPassword, _
		             encryptionKeyUserId)
 
    Return signedString
   Else
    Console.WriteLine("No key with user Id:" + _
	                  encryptionKeyUserId + _
	                  " was found in this key store.")
    Return String.Empty
   End If
 End Function
End Class

Back to Top

5. Sign and encrypt a Stream

In the example below you can see how to encrypt a Stream of data. The encrypted result is stored in a MemoryStream, but it can be any other kind of Stream that supports writing

C# example

using System;
using System.IO;
using DidiSoft.Pgp;
 
class SignAndEncryptStreamDemo
{
 public static void Demo()
 {
  // create an instance of the library
  PGPLib pgp = new PGPLib();
 
  // is output ASCII or binary            
  bool asciiArmor = true;
  // should integrity check information be added
  // set to true for compatibility with GnuPG 2.2.8+
  bool withIntegrityCheck = false;
 
  // In this example the output is a memory stream
  MemoryStream encryptedOutput = new MemoryStream();
 
  using (Stream dataStream = File.OpenRead(@"DataFiles\INPUT.txt"))
  using (Stream privateSigningKeyStream = File.OpenRead(@"DataFiles\private.key"))
  using (Stream publicEncryptionKeyStream = File.OpenRead(@"DataFiles\public.key"))
  {
   string privateKeyPassword = "changeit";
 
   // We have to associate a file name label with the encrypted data
   // we can also use the constant PGPLib.CONSOLE for very sensitive data
   string internalFileNameLabel = "INPUT.txt";
 
   pgp.SignAndEncryptStream(dataStream,
			   internalFileNameLabel,
			   privateSigningKeyStream,
			   privateKeyPassword,
			   publicEncryptionKeyStream,
			   encryptedOutput,
			   asciiArmor,
			   withIntegrityCheck);
  }
 
  // the memory stream needs to be reset if we want to read from it afterwards
  encryptedOutput = new MemoryStream(encryptedOutput.GetBuffer(), 
					0, 
					(int)encryptedOutput.Position);
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Public Class SignAndEncryptStream
 Public Shared Sub Demo()
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  ' is output ASCII or binary            
  Dim asciiArmor As Boolean = True
  ' should integrity check information be added
  ' set to true for compatibility with GnuPG 2.2.8+
  Dim withIntegrityCheck As Boolean = False
 
  ' In this example the output is a memory stream
  Dim encryptedOutput As New MemoryStream()
 
  Using dataStream As Stream = File.OpenRead("DataFiles\INPUT.txt")
   Using privateSigningKeyStream As Stream = File.OpenRead("DataFiles\private.key")
    Using publicEncryptionKeyStream As Stream = File.OpenRead("DataFiles\public.key")
     Dim privateKeyPassword As String = "changeit"
 
     ' We have to associate a file name label with the encrypted data
     ' we can also use the constant PGPLib.CONSOLE for very sensitive data
     Dim internalFileNameLabel As String = "INPUT.txt"
 
     pgp.SignAndEncryptStream(dataStream, _
				internalFileNameLabel, _
				privateSigningKeyStream, _
				privateKeyPassword, _
				publicEncryptionKeyStream, _
				encryptedOutput, _
				asciiArmor, _
				withIntegrityCheck)
    End Using
   End Using
  End Using
 
  ' the memory stream needs to be reset if we want to read from it afterwards
  encryptedOutput = New MemoryStream(encryptedOutput.GetBuffer(), 0, _
					CInt(encryptedOutput.Position))
 End Sub
End Class

Back to Top

6. Sign and encrypt a Stream with keys located in a KeyStore

This example is equivalent to the above one, except that the keys are located in a KeyStore object.

C#

using System;
using System.IO;
using DidiSoft.Pgp;
 
class KeyStoreSignAndEncryptStream
{
 public static void Demo()
 {
  // initialize the key store
  KeyStore keyStore = new KeyStore(@"mykey.store", "store pass");
 
  // create an instance of the library
  PGPLib pgp = new PGPLib();
 
  // specify should the output be ASCII or binary
  bool asciiArmor = false;
  // should additional integrity information be added, set to true for compatibility with GnuPG 2.2.8+    
  bool withIntegrityCheck = false;
 
  // User Id or Key Hex Id of the signing key, this is usually our private key
  string signUserId = "support@didisoft.com";
  string privateKeyPassword = "changeit";
 
  // User Id or Key Hex Id of the recipient's public key
  string encUserId = "recipient@company.com";
 
  // In this example the output is a memory stream
  MemoryStream encryptedOutput = new MemoryStream();
 
  // We have to associate a file name label with the encrypted data
  // we can also use the constant PGPLib.CONSOLE for very sensitive data
  string internalFileNameLabel = "INPUT.txt";
 
  using (Stream dataStream = File.OpenRead(@"DataFiles\INPUT.txt"))
  {
	pgp.SignAndEncryptStream(dataStream,
				internalFileNameLabel,
				keyStore,
				signUserId,
				privateKeyPassword,
				encUserId,
				encryptedOutput,
				asciiArmor,
				withIntegrityCheck);
  }
 
  // the memory stream needs to be reset if we want to read from it afterwards
  encryptedOutput = new MemoryStream(encryptedOutput.GetBuffer(),
					0,
					(int)encryptedOutput.Position);
 }
}

VB.NET example

Imports System
Imports System.IO
Imports DidiSoft.Pgp
 
Class KeyStoreSignAndEncryptStream
 Public Shared Sub Demo()
  ' initialize the key store
  Dim keyStore As New KeyStore("mykey.store", "store pass")
 
  ' create an instance of the library
  Dim pgp As New PGPLib()
 
  ' specify should the output be ASCII or binary
  Dim asciiArmor As Boolean = False
  ' should additional integrity information be added, set to true for compatibility with GnuPG 2.2.8+    
  Dim withIntegrityCheck As Boolean = False
 
  ' User Id or Key Hex Id of the signing key, this is usually our private key
  Dim signUserId As String = "support@didisoft.com"
  Dim privateKeyPassword As String = "changeit"
 
  ' User Id or Key Hex Id of the recipient's public key
  Dim encUserId As String = "recipient@company.com"
 
  ' In this example the output is a memory stream
  Dim encryptedOutput As New MemoryStream()
 
  ' We have to associate a file name label with the encrypted data
  ' we can also use the constant PGPLib.CONSOLE for very sensitive data
  Dim internalFileNameLabel As String = "INPUT.txt"
 
  Using dataStream As Stream = File.OpenRead("DataFiles\INPUT.txt")
	pgp.SignAndEncryptStream(dataStream, _
				internalFileNameLabel, _
				keyStore, _
				signUserId, _
				privateKeyPassword, _
				encUserId, _
				encryptedOutput, _
				asciiArmor, _
				withIntegrityCheck)
  End Using
 
  ' the memory stream needs to be reset if we want to read from it afterwards
  encryptedOutput = New MemoryStream(encryptedOutput.GetBuffer(), 0, _
					CInt(encryptedOutput.Position))
 End Sub
End Class

Back to Top

7. Sign and encrypt a file with the old style of OpenPGP digital signatures

Here we show how to sign and encrypt a file with the old style of OpenPGP signatures. This way the produced output can be decrypted and the signature verified by older OpenPGP implementations among which PGP 6.5.8 and McAfee E-Business Server 7.x.

C# example

using System;
using DidiSoft.Pgp;
 
public class SignAndEncryptV3
{
  public void Demo()
  {
    // create an instance of the library
    PGPLib pgp = new PGPLib();
    // is output ASCII or binary
    bool asciiArmor = false;
 
    // sign and encrypt
    pgp.SignAndEncryptFileV3(@"C:\Test\INPUT.txt",
                           @"C:\Test\private.key",
                           "private key password",
                           @"C:\Test\public.key",
                           @"C:\Test\OUTPUT.pgp",
                           asciiArmor);
    }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class SignAndEncryptV3
  Public Sub Demo()
    ' create an instance of the library
    Dim pgp As New PGPLib()
    ' is output ASCII or binary
    Dim asciiArmor As Boolean = False
 
    ' sign and encrypt
    pgp.SignAndEncryptFileV3("C:\Test\INPUT.txt", _
		           "C:\Test\private.key", _
			   "private key password", _
			   "C:\Test\public.key", _
			   "C:\Test\OUTPUT.pgp", _
			   asciiArmor)
  End Sub
End Class

Back to Top

8. Sign and encrypt in one pass with the old OpenPGP signatures and a KeyStore

In this example we sign and encrypt a file in one pass with OpenPGP keys stored in KeyStore object. We should know either the User Id of the key owner or the key Id prior calling the SignAndEncryptFileV3 method (For more KeyStore examples see the KeyTool project that ships with the library).

C# example

using System;
using DidiSoft.Pgp;
 
public class KeyStoreSignAndEncryptFileV3
{
  public static void Demo()
  {
    // initialize the Key store
    KeyStore keyStore = new KeyStore(@"c:\key.store",
					"keystore pass");
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    // is output ASCII or binary
    bool asciiArmor = true;
 
    String signUserId = "support@didisoft.com";
    String signKeyPassword = "private key password";
    String encUserId = "recipient@company.com";
 
    // sign and encrypt
    pgp.SignAndEncryptFileV3(@"DataFiles\INPUT.txt",
			keyStore,
			signUserId,
			signKeyPassword,
			encUserId,
			@"DataFiles\OUTPUT.pgp",
			asciiArmor);
  }
}

VB.NET example

Imports System
Imports DidiSoft.Pgp
 
Public Class KeyStoreSignAndEncryptFileV3
 Public Shared Sub Demo()
   ' initialize the key store
   Dim keyStore As New KeyStore("DataFiles\key.store", _
				"keystore password")
   ' create an instance of the library
   Dim pgp As New PGPLib()
 
   ' is output ASCII or binary
   Dim asciiArmor As Boolean = True
 
   Dim signUserId As String = "support@didisoft.com"
   Dim signKeyPassword As String = "private key password"
   Dim encUserId As String = "recipient@company.com"
 
   pgp.SignAndEncryptFileV3("DataFiles\INPUT.txt", _
			 keyStore, _
			 signUserId, _
			 signKeyPassword, _
			 encUserId, _
			"DataFiles\OUTPUT.pgp", _
                         asciiArmor)
 End Sub
End Class

Back to Top

A. Exception Handling

All SignAndEncrypt methods throw System.IO.IOException and DidiSoft.Pgp.PGPException. The later one can be tracked to a number of sub classes residing in the DidiSoft.Pgp.Exceptions namespace in order to identify more thoroughly what went wrong. The example below illustrates an example exception handling with the various expected exceptions:

C# example

PGPLib pgp = new PGPLib();
try
{
  pgp.Sign...
}
catch (System.IO.IOException e)
{
  // in case of an input file not found or other I/O related error
}
catch (DidiSoft.Pgp.PGPException e)
{
  if (e is DidiSoft.Pgp.Exceptions.WrongPrivateKeyException)
  {
   // The supplied private key source is not a private key at all 
   // or does not contain a signing key
   // For example we have supplied an arbitrary file for the private 
   // key parameter, or in the case with a KeyStore parameter 
   // there is no private key with the specified Key ID or User ID
  }
  else if (e is DidiSoft.Pgp.Exceptions.WrongPasswordException)
  {
   // The supplied private key password is misspelled
  }
  else if (e is DidiSoft.Pgp.Exceptions.WrongPublicKeyException)
  {
   // The supplied public key is not a public key at all 
   // or does not contain an encryption key
   // For example we have supplied an arbitrary file for the public 
   // key file parameter, or in the case with a KeyStore parameter 
   // there is no key with the specified Key ID or User ID
  }
  else if (e is DidiSoft.Pgp.Exceptions.KeyIsExpiredException)
  {
   // A supplied public key is expired 
   // (the system date is after the date specified inside the key 
   // as an expiration date)
   // We can still use such keys by setting the property UseExpiredKeys to true
  }
  else if (e is DidiSoft.Pgp.Exceptions.KeyIsRevokedException)
  {
   // A supplied public key is revoked
   // (the key contains a revocation signature that marks it as not usable)
   // We can still use such keys by setting the property UseRevokedKeys to true
  }
  else
  {
   // General OpenPGP error non among the above
  }
}

VB.NET example

Dim pgp As New PGPLib()
Try
  pgp.Sign...
Catch e As System.IO.IOException
  ' in case of an input file not found or other I/O related error
Catch e As DidiSoft.Pgp.PGPException
  If TypeOf e Is DidiSoft.Pgp.Exceptions.WrongPrivateKeyException Then
   ' The supplied private key source is not a private key at all 
   ' or does not contain a signing key
   ' For example we have supplied an arbitrary file for the private 
   ' key parameter, or in the case with a KeyStore parameter 
   ' there is no private key with the specified Key ID or User ID	
  ElseIf TypeOf e Is DidiSoft.Pgp.Exceptions.WrongPasswordException Then
   ' The supplied private key password is misspelled	
  ElseIf TypeOf e Is DidiSoft.Pgp.Exceptions.WrongPublicKeyException Then
   ' The supplied public key is not a public key at all or does not 
   ' contain an encryption key
   ' For example we have supplied an arbitrary file for the 
   ' public key file parameter, or in the case with a KeyStore there is 
   ' no key with the specified Key ID or User ID	
  ElseIf TypeOf e Is DidiSoft.Pgp.Exceptions.KeyIsExpiredException Then
   ' A supplied public key is expired 
   ' (the system date is after the date specified inside the key 
   ' as an expiration date)
   ' We can still use such keys by setting the property UseExpiredKeys to true	
  ElseIf TypeOf e Is DidiSoft.Pgp.Exceptions.KeyIsRevokedException Then
   ' A supplied public key is revoked
   ' (the key contains a revocation signature that marks it as not usable)
   ' We can still use such keys by setting the property UseRevokedKeys to true	
  Else
   ' General OpenPGP error non among the above	
  End If
End Try

Back to Top

Summary

In this chapter we have demonstrated how to achieve OpenPGP one pass sign and encrypt with DidiSoft OpenPGP Library for .NET.

You may also check how to decrypt and verify the output generated from the above examples, or continue with the topics that discuss clear text signing and detached signing.

If you have to send data to older PGP 2.x systems check how to enable compatibility.

List of methods used:

PGPLib.SignAndEncryptFile Signs and encrypts a file in one pass
PGPLib.SignAndEncryptFileV3 Signs and encrypts a file in one pass generating old style OpenPGP signatures
PGPLib.SignAndEncryptString Signs and encrypts a String message in one pass
PGPLib.SignAndEncryptStream Signs and encrypts a source Stream into another output Stream