Introduction
This article presents GnuPGWrapper
v1.0, a wrapper class for GnuPG.
GnuPG stands for GNU Privacy Guard and is GNU's tool for secure communication and data storage. It can be used to encrypt data and to create digital signatures. It includes an advanced key management facility and is compliant with the proposed OpenPGP Internet standard as described in RFC 2440. As such, GnuPG is a complete and free replacement for PGP (Pretty Good Privacy).
This article provides a C# wrapper class (GnuPGWrapper
) that will enable use of OpenPGP Internet encryption standard within a .NET world. It is shipped with a demo ASP.NET Web Form (GnuPG.aspx) which calls the wrapper class.
Installation
Prerequisites
- Complete .NET Environment, e.g. Windows XP Professional + IIS 5.0 + .NET Framework SDK
- GnuPG for Windows (more about GnuPG)
Procedure
Background
GnuPG ships as a command line program (gpg.exe) acting as a filter (reads from standard input and writes into standard output). Although suitable for scripting on UNIX systems (where calling a command line program from sh or bash is easy), it's pretty hard to integrate this in a production .NET environment.
The GnuPG Wrapper executes the command line program (gpg.exe) in a different process, redirects standard input (stdin
), standard output (stdout
) and standard error (stderr
) streams, and monitors the streams to fetch the results of the encryption/signing operation.
Please note that you must have INSTALLED GnuPG AND generated/imported the appropriate keys before using this class. Refer to the GnuPG manual to do this...
Using the code
In order to use the wrapper class, you need to proceed as follows:
- Create an instance of the class
- Set the
command
property to the requested command (SignAndEncrypt
, Encrypt
, Decrypt
, Sign
, Verify
)
- Optionally, set parameters for the command (home directory, originator, recipients, etc...)
- Call the
ExecuteCommand
method with input/output strings variables
The next sections show sample source code for the most command operation (SignAndEncrypt
, Decrypt
, Verify
).
Encrypt and Sign
using Emmanuel.Cryptography.GnuPG;
GnuPGWrapper gpg = new GnuPGWrapper();
gpg.command = Commands.SignAndEncrypt;
gpg.homedirectory = Server.MapPath
(ConfigurationSettings.AppSettings["homedirectory"]);
gpg.passphrase = ConfigurationSettings.AppSettings["passphrase"];
gpg.originator = FromTextBox.Text;
gpg.recipient = ToTextBox.Text;
string inputText = MessageTextBox.Text;
string outputText = "";
gpg.ExecuteCommand(inputText, out outputText);
OutputTextBox.Text = outputText;
OutputTextBox.Visible = true;
ErrorMessage.Visible = false;
ExitCodeLabel.Text = gpg.exitcode.ToString();
Decrypt
using Emmanuel.Cryptography.GnuPG;
GnuPGWrapper gpg = new GnuPGWrapper();
gpg.homedirectory = "C:\Inetpub\wwwroot\GnuPGDotNet\GnuPG"
gpg.passphrase = "My passphrase is so cool I can't remember it"
gpg.command = Commands.Decrypt;
string outputText = "";
gpg.ExecuteCommand("This is a test message.", out outputText);
[...]
Verify
using Emmanuel.Cryptography.GnuPG;
GnuPGWrapper gpg = new GnuPGWrapper();
gpg.homedirectory = "C:\Inetpub\wwwroot\GnuPGDotNet\GnuPG"
gpg.passphrase = "My passphrase is so cool I can't remember it"
gpg.originator = "me@mycompany.com";
gpg.command = Commands.Verify;
string outputText = "";
gpg.ExecuteCommand("This is a test message.", out outputText);
[...]
Error handling
Error handling is done via a specific Exception
class; method ExecuteCommand
raises this exception whenever an error occurs. You calling application can handle this exception as follows:
using Emmanuel.Cryptography.GnuPG;
try
{
GnuPGWrapper gpg = new GnuPGWrapper();
gpg.homedirectory = "C:\Inetpub\wwwroot\GnuPGDotNet\GnuPG"
gpg.passphrase = "My passphrase is so cool I can't remember it"
gpg.originator = "me@mycompany.com";
gpg.recipient = "you@yourcompany.com";
gpg.command = Commands.SignAndEncrypt;
string outputText = "";
gpg.ExecuteCommand("This is a test message.", out outputText);
[...]
}
catch (GnuPGException gpge)
{
ErrorMessage.Text = gpge.Message;
}
Points of interest
The GnuPG wrapper:
- Doesn't use any temporary files to store results; it directly uses streams/pipes.
- Uses multiple threads to read data from standard input and standard error, preventing any deadlocks.
- Uses configurable timeouts to prevent blocking calling applications in case of a system/program/process crash
- Uses a configurable passphrase, which can be stored in a local configuration file (Web.Config) to prevent disclosure of the phrase
About GnuPG and PGP
This class has been developed and tested with GnuPG v1.2.0 (MingW32).
You can check the command line manual page for gpg.exe.
For more about GNU, please refer to http://www.gnu.org/. For more about GnuPG, please refer to http://www.gnupg.org/. For more about OpenPGP (RFC 2440), please refer to http://www.gnupg.org/rfc2440.html. For more about PGP, please refer to http://www.pgpi.org/.
History
- Date posted: October 30th, 2002
- Updated: September 19th, 2003