Using the Gnu Privacy Guard (GnuPG/PGP) within ASP.NET [v1.0]


Application Security Testing: An Integral Part of DevOps

Click here for a larger image.

Environment: .NET, ASP.NET, C#

Keywords: GnuPG, PGP, Cryptography, Thread, Process, Command Line Program

GnuPG Wrapper

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 the use of an 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.



  • Complete ASP .NET Environment—Windows XP Professional + IIS 5.0 + .NET Framework SDK
  • GnuPG for Windows (more about GnuPG)


  • Download the zip file (GnuPGDotNet_src.zip)
  • Extract the zip file (for example, into directory "C:\Inetpub\wwwroot\")
  • Using Administrative Tools/Internet Information Services, create an IIS Application for directory GnuPGDotNet
  • Call demo Web Form via URL http://localhost/GnuPGDotNet/GnuPG.aspx


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.

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.

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....

Sample Code

To use the wrapper class, you need to proceed as follows:

  1. Create an instance of the class
  2. Set the "command" property to the requested command (SignAndEncrypt, Encrypt, Decrypt, Sign, Verify)
  3. Optionally, set parameters for the command (home directory, originator, recipients, and so forth)
  4. Call the "ExecuteCommand" method with input/output strings variables

The next sections show sample source code for the most command operations (SignAndEncrypt, Decrypt, Verify).

Encrypt and Sign

  // Reference My GnuPG wrapping class
  using Emmanuel.Cryptography.GnuPG;

  // Create GnuPG wrapping class
  GnuPGWrapper gpg = new GnuPGWrapper();

  // Set command
  gpg.command = Commands.SignAndEncrypt;

  // Set some parameters from on Web.Config file
  gpg.homedirectory = Server.MapPath(ConfigurationSettings.
  gpg.passphrase = ConfigurationSettings.AppSettings

  // Set other parameters from Web Controls
  gpg.originator = FromTextBox.Text;
  gpg.recipient = ToTextBox.Text;

  // Declare input/output variables (input is also read from a
  // Web control)
  string inputText = MessageTextBox.Text;
  string outputText = "";

  // Execute GnuPG
  gpg.ExecuteCommand(inputText, out outputText);

  // Display output text
  OutputTextBox.Text = outputText;
  OutputTextBox.Visible = true;
  ErrorMessage.Visible = false;
  ExitCodeLabel.Text = gpg.exitcode.ToString();


  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;

  // Execute GnuPG
  string outputText = "";
  gpg.ExecuteCommand("This is a test message.", out outputText);

  // Display output text


  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;

  // Execute GnuPG
  string outputText = "";
  gpg.ExecuteCommand("This is a test message.", out outputText);

  // Display output text

Error Handling

Error handling is done via a specific Exception class; method "ExecuteCommand" raises this exception whenever an error occurs. Your calling application can handle this exception as follows:

  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
    gpg.originator = "me@mycompany.com";
    gpg.recipient = "you@yourcompany.com";
    gpg.command = Commands.SignAndEncrypt;

    // Execute GnuPG
    string outputText = "";
    gpg.ExecuteCommand("This is a test message.", out outputText);

    // Display output text

  catch (GnuPGException gpge)
    // Display error message
    ErrorMessage.Text = gpge.Message; // Contains a clear text
                                      // error message, either
                                      // from the wrapper or
                                      // from gpg.exe itself

Real-Life Deployment

This code is deployed in a real-life e-commerce Web site that uses GnuPG to communicate with some of its partners (http://www.gourmeo.com).

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


Download source and demo - 535 Kb


  • Encryption Key Path.

    Posted by kanagaraj k on 06/28/2016 04:51am

    Is it possible to add (public/private) key directly in code?

  • File Problem

    Posted by Jack on 09/21/2014 07:33pm

    This code is not use for big files ? e.g. 125 kb . But I want to encrypt/decrypt 100 MB file. what can I do ? Thanks for opinion.

  • Making it work with lager files...

    Posted by benhull on 05/28/2008 09:10am

    This wrapper has a giant flaw. Once the process buffer is full, it locks. Due to the single threading the writing and reading at the same time. The class only creates threading for Error input and standard outputs. If you want this to work... do not use the class and put this in your code. The process object becomes full and has to buffer out. Which, it cannot because you have not read the data out of the buffer yet(buffered output). You need to create a thread and read and write it your self. Code--- // in the send string, add your reciepent email address where bhull@racetrac.com is. static string send = "--homedir \"C:\\gnupg\" --yes --batch --encrypt --armor --recipient bhull@racetrac.com --verbose "; static ProcessStartInfo startinfo = new ProcessStartInfo(@"C:\gnupg\gpg.exe", send); static Process procstart; static string _outputString; startinfo.WorkingDirectory = GnupgHome; startinfo.CreateNoWindow = true; startinfo.UseShellExecute = false; startinfo.RedirectStandardInput = true; startinfo.RedirectStandardOutput = true; startinfo.RedirectStandardError = true; procstart = Process.Start(startinfo); procstart.StandardInput.AutoFlush = false; Thread writer = new Thread(delegate() { procstart.StandardInput.WriteLine(_ResultSet); procstart.StandardInput.Close(); }); writer.Start(); // whatever you want to do here do it. write to file or whatever writer.join();

  • large file support

    Posted by Legacy on 12/16/2003 12:00am

    Originally posted by: TM

    does the component have problems dealing (encryption/decryption) with large files?

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.