The OpenPGP clear text signed format is designed for text data. The digital signature is appended after the clear text original message; this way the recipient can still read it without using special software. The examples below show how to produce clear signed messages with DidiSoft OpenPGP Library for .NET
List of examples
Clear text signing a file
1. with a private key located in a file
2. with a private key located in a KeyStore
Clear text signing a String message
3. with a private key located in a file
4. with a private key located in a KeyStore
Clear text signing a Stream
5. with a private key supplied as a Stream
6. with a private key located in a KeyStore
Clear text signing a file with the old version 3 signature
7. with a private key located in a file
Appendix
A. Verifying and extracting clear text signed data
1. Clear text signing a file with a private key located in a file
C# example
using System.IO; using DidiSoft.Pgp; class ClearSignFile { public static void Demo() { // create an instance of the library PGPLib pgp = new PGPLib(); // clear text sign pgp.ClearSignFile(new FileInfo(@"DataFiles\INPUT.txt"), new FileInfo(@"DataFiles\my_private_key.asc"), "private key password", HashAlgorithm.SHA256, new FileInfo(@"DataFiles\OUTPUT.sig.txt")); } } |
VB.NET code
Imports System.IO Imports DidiSoft.Pgp Class ClearSignFile Public Shared Sub Demo() ' create an instance of the library Dim pgp As New PGPLib() ' clear text sign pgp.ClearSignFile(New FileInfo("DataFiles\INPUT.txt"), _ New FileInfo("DataFiles\private.key"), _ "private key password", _ HashAlgorithm.SHA256, _ New FileInfo("DataFiles\OUTPUT.sig.txt")) End Sub End Class |
2. Clear text sign a file with a private key located in a KeyStore
In this example, the signing key is located in a KeyStore. The key is specified through its User ID but can be specified also with its Key ID or Key Hex ID.
C# example
using System; using DidiSoft.Pgp; class KeyStoreClearSignFile { public static void Demo() { // initialize the key store KeyStore ks = new KeyStore(@"DataFiles\key.store", "keystore password"); string signingKeyUserId = "support@didisoft.com"; string signingKeyPassword = "my private key password"; // if this key store contains a key with // the desired recipient userId, then clear sign, // otherwise notify that there is no such key if (ks.ContainsKey(signingKeyUserId)) { // create an instance of the library PGPLib pgp = new PGPLib(); // clear text sign pgp.ClearSignFile(@"DataFiles\INPUT.txt", ks, signingKeyUserId, signingKeyPassword, HashAlgorithm.SHA1, @"DataFiles\OUTPUT.sig.txt"); } else { Console.WriteLine("No key with user Id:" + signingKeyUserId + " was found in this key store."); } } } |
VB.NET example
Imports System Imports DidiSoft.Pgp Class KeyStoreClearSignFile Public Shared Sub Demo() ' initialize the key store Dim ks As New KeyStore("DataFiles\key.store", "keystore password") Dim signingKeyUserId As String = "support@didisoft.com" Dim signingKeyPassword As String = "my private key password" ' if this key store contains a key with ' the desired recipient userId, then clear sign, ' otherwise notify that there is no such key If ks.ContainsKey(signingKeyUserId) Then ' create an instance of the library Dim pgp As New PGPLib() ' clear text sign pgp.ClearSignFile("DataFiles\INPUT.txt", ks, _ signingKeyUserId, _ signingKeyPassword, _ HashAlgorithm.SHA1, _ "DataFiles\OUTPUT.sig.txt") Else Console.WriteLine("No key with user Id:" + signingKeyUserId + " was found in this key store.") End If End Sub End Class |
3. Clear signing a String message with a private key located in a file
C# example
using System; using System.IO; using DidiSoft.Pgp; class ClearSignString { public static String Demo() { String plainString = "Hello World"; PGPLib pgp = new PGPLib(); String clearSignedString = pgp.ClearSignString(plainString, new FileInfo(@"DataFiles\my_private_key.asc"), "private key password", HashAlgorithm.SHA1); return clearSignedString; } } |
VB.NET code
Imports System Imports System.IO Imports DidiSoft.Pgp Class ClearSignString Public Shared Function Demo() As String Dim plainString As String = "Hello World" ' create an instance of the library Dim pgp As New PGPLib() ' clear text sign Dim clearSignedString As String = _ pgp.ClearSignString(plainString, _ New FileInfo("DataFiles\my_private_key.asc"), _ "my private key password", _ HashAlgorithm.SHA1) Return clearSignedString End Function End Class |
4. Clear text signing a String message with a private key located in a KeyStore
C# example
using System; using DidiSoft.Pgp; class KeyStoreClearSignString { public static String Demo() { // initialize the key store KeyStore ks = new KeyStore(@"DataFiles\key.store", "keystore password"); string signingKeyUserId = "support@didisoft.com"; string signingKeyPassword = "private key password"; // if this key store contains a key with the desired recipient userId - clear sign, // otherwise notify that there is no such key if (ks.ContainsKey(signingKeyUserId)) { // create an instance of the library PGPLib pgp = new PGPLib(); string plainText = "Hello World"; // clear text sign string clearSignedString = pgp.ClearSignString( plainText, ks, signingKeyUserId, signingKeyPassword, HashAlgorithm.SHA1); return clearSignedString; } else { Console.WriteLine("No key with user Id:" + signingKeyUserId + " was found in this key store."); return null; } } } |
VB.NET example
Imports System Imports DidiSoft.Pgp Class KeyStoreClearSignString Public Shared Function Demo() As String Dim signingKeyUserId As String = "support@didisoft.com" Dim signingKeyPassword As String = "private key password" ' 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 - clear sign, ' otherwise notify that there is no such key If ks.ContainsKey(signingKeyUserId) Then Dim pgp As New PGPLib() Dim plainText As String = "Hello World" Dim clearSignedString As String = _ pgp.ClearSignString(plainText, ks, _ signingKeyUserId, _ signingKeyPassword, _ HashAlgorithm.SHA1) Return clearSignedString Else Console.WriteLine("No key with user Id:" + _ signingKeyUserId + _ " was found in this key store.") Return Nothing End If End Function End Class |
5. Clear text signing a Stream with a private key supplied as a Stream
In this example, we will create a clear text signed output of data available as a Stream for reading.
C# code
using System; using System.IO; using DidiSoft.Pgp; public class ClearSignStream { public static void Demo() { // create an instance of the library PGPLib pgp = new PGPLib(); Stream outputStream = new MemoryStream(); using (Stream dataStream = File.OpenRead(@"DataFiles\INPUT.txt")) using (Stream keyStream = File.OpenRead(@"DataFiles\my_private_key.asc")) { // clear text sign pgp.ClearSignStream(dataStream, keyStream, "private key password", HashAlgorithm.SHA256, outputStream); } // .. The outputStream Position is at the end of the Stream } } |
VB.NET example
Imports System Imports System.IO Imports DidiSoft.Pgp Class ClearSignStream Public Shared Sub Demo() ' create an instance of the library Dim pgp As New PGPLib() Dim outputStream As Stream = New MemoryStream() Using Stream dataStream = File.OpenRead(@"DataFiles\INPUT.txt") Using Stream keyStream = File.OpenRead(@"DataFiles\my_private_key.asc") ' clear text sign pgp.ClearSignStream(dataStream, _ keyStream, _ "private key password", _ HashAlgorithm.SHA256, _ outputStream) End Using End Using ' .. The outputStream Position is at the end of the Stream End Sub End Class |
6. Clear text signing a Stream with a private key located in a KeyStore
In this example, the signing key is located in a KeyStore. The key is specified through its Key Hex ID but can be specified also with its Key ID (of type System.Int64) or User ID
C# example
using System; using System.IO; using DidiSoft.Pgp; class KeyStoreClearSignStream { public static void Demo() { // initialize the key store KeyStore ks = new KeyStore(@"DataFiles\key.store", "keystore password"); string signingKeyHexId = "395A421B"; string signingKeyPassword = "my private key password"; // create an instance of the library PGPLib pgp = new PGPLib(); Stream outputStream = new MemoryStream(); using (Stream dataStream = File.OpenRead(@"DataFiles\INPUT.txt")) { // clear text sign pgp.ClearSignStream(dataStream, ks, signingKeyHexId, signingKeyPassword, HashAlgorithm.SHA1, outputStream); } // .. The outputStream Position is at the end of the Stream } } |
VB.NET example
Imports System Imports System.IO Imports DidiSoft.Pgp Class KeyStoreClearSignStream Public Shared Sub Demo() ' initialize the key store Dim ks As New KeyStore("DataFiles\key.store", "keystore password") Dim signingKeyHexId As String = "395A421B" Dim signingKeyPassword As String = "my private key password" ' create an instance of the library Dim pgp As New PGPLib() Dim outputStream As Stream = New MemoryStream() Using Stream dataStream = File.OpenRead(@"DataFiles\INPUT.txt") ' clear text sign pgp.ClearSignStream(dataStream, ks, _ signingKeyHexId, _ signingKeyPassword, _ HashAlgorithm.SHA1, _ outputStream) End Using ' .. The outputStream Position is at the end of the Stream End Sub End Class |
7. Clear text signing a file with the old version 3 signatures
Older OpenPGP implementations used a different signature format and if we wish to create a clear text signed message that can be verified by them, we should use the methods that end with V3. Newer implementations can process both the old and the new signature format.
C# example
using System.IO; using DidiSoft.Pgp; class ClearSignFile { public static void Demo() { // create an instance of the library PGPLib pgp = new PGPLib(); // clear text sign pgp.ClearSignFileV3(new FileInfo(@"DataFiles\INPUT.txt"), new FileInfo(@"DataFiles\my_private_key.asc"), "private key password", HashAlgorithm.SHA256, new FileInfo(@"DataFiles\OUTPUT.sig.txt")); } } |
VB.NET example
Imports System.IO Imports DidiSoft.Pgp Class ClearSignFile Public Shared Sub Demo() ' create an instance of the library Dim pgp As New PGPLib() ' clear text sign pgp.ClearSignFileV3(new FileInfo("DataFiles\INPUT.txt"), _ new FileInfo("DataFiles\my_private_key.asc"), _ "private key password", _ HashAlgorithm.SHA256, _ new FileInfo("DataFiles\OUTPUT.sig.txt")) End Sub End Class |
Appendix A. Verifying and extracting clear text signed data
Verification and extraction of clear-signed data are done through the verification methods.
A key difference is that when we supply a wrong public key nonmatching the signature, or a KeyStore with no matching public key in it a DidiSoft.Pgp.Exceptions.WrongPublicKeyException will be thrown:
C# example
PGPLib pgp = new PGPLib(); string signed = pgp.ClearSignString("Hello world", "my_private_key.asc", "my password", HashAlgorithm.SHA1); string extracted = string.Empty; bool verified = false; try { verified = pgp.VerifyString(signed, "wrong_pub_key.asc", out extracted); } catch (DidiSoft.Pgp.Exceptions.WrongPublicKeyException) { Console.WriteLine("The specified public key doesn't match the signature, you should use another key"); // simply extract the clear text data extracted = pgp.DecryptString(signed, null, string.Empty); } |
VB.NET example
Dim pgp As New PGPLib() Dim signed As String = pgp.ClearSignString("Hello world", "my_private_key.asc", "my password", HashAlgorithm.SHA1) Dim extracted As String = String.Empty Dim verified As Boolean = False Try verified = pgp.VerifyString(signed, "wrong_pub_key.asc", extracted) Catch (DidiSoft.Pgp.Exceptions.WrongPublicKeyException) Console.WriteLine("The specified public key doesn't match the signature, you should use another key"); // simply extract the clear text data extracted = pgp.DecryptString(signed, null, string.Empty); End Try |
Appendix B. Exception Handling
All ClearSign methods throw System.IO.IOException and DidiSoft.Pgp.PGPException. We can try to cast the DidiSoft.Pgp.PGPException variable in its catch clause in order to identify what exactly went wrong.
Below is an example that illustrates the subclasses that we can try to cast the exception of type DidiSoft.Pgp.PGPException to:
C# example
PGPLib pgp = new PGPLib(); try { pgp.ClearSign... } 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 { // General OpenPGP error non among the above } } |
VB.NET example
Dim pgp As New PGPLib() Try pgp.ClearSign... 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 Else ' General OpenPGP error non among the above End If End Try |
Summary
This chapter presented OpenPGP cleartext signing in C# and VB.NET. The class PGPLib that provides those methods is located in the namespace DidiSoft.Pgp. The methods that perform cleartext signing are:
PGPLib.ClearSignFile
PGPLib.ClearSignString
PGPLib.ClearSignStream
PGPLib.ClearSignFileV3