Click here to Skip to main content
Click here to Skip to main content

Automated File Decryption Using GnuPG and C#

, 11 Dec 2007
Rate this:
Please Sign up or sign in to vote.
How To: Automate decryption of PGP / GnuPG encrypted files.

Introduction

Suppose you need to decrypt and process a PGP / GnuPG encrypted file. This brief how-to will hopefully help you do that.

Background

The set up: our client needed to provide us - securely - with an XML file made available via FTP, daily. Secure FTP was not an option, and they insisted on PGP. No problem, right? Well, actually quite a few problems, which I will attempt to help you avoid here.

Obviously, you need to install PGP or its open-source pal, GnuPG. You need to create a private and public key for yourself, and provide the public key to the "encryptor". All this stuff is well documented on various sites, so I'm not going into it here. There's a nice little Windows app called "GNU Privacy Assistant" (I used version v0.5.0) that will make this job fast and easy. Google it, or get it through www.gnupg.org.

End result: a human-unreadable / GPG-encrypted document that now needs to be decrypted and processed by an automated process.

Using the code

Here's the method we use. Basically, grab your encrypted file from the file system and get a reference to it through the FileInfo class. Pass that to the method.

private string DecryptFile(FileInfo encryptedFile)
{
  // decrypts the file using GnuPG, saves it to the file system
  // and returns the new (decrypted) file name.

  // encrypted file: thefile.xml.gpg decrypted: thefile.xml

  string outputFileName = this.GetDecryptedFileName(encryptedFile);
  // whatever you want here - just a convention

  string path = encryptedFile.DirectoryName;
  string outputFileNameFullPath = path + "\\" + outputFileName;
  try {
      System.Diagnostics.ProcessStartInfo psi = 
        new System.Diagnostics.ProcessStartInfo("cmd.exe");
      psi.CreateNoWindow = true;
      psi.UseShellExecute = false;
      psi.RedirectStandardInput = true;
      psi.RedirectStandardOutput = true;
      psi.RedirectStandardError = true;
      psi.WorkingDirectory = "C:\\Program Files\\GnuPP\\GnuPG";

      System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi);
      // actually NEED to set this as a local string variable
      // and pass it - bombs otherwise!
      string sCommandLine = "echo " + this._passphrase + 
                            "| gpg.exe --passphrase-fd 0 -o \"" +
      outputFileNameFullPath + "\" --decrypt \"" + 
                               encryptedFile.FullName + "\"";
      process.StandardInput.WriteLine(sCommandLine);
      process.StandardInput.Flush();
      process.StandardInput.Close();
      process.WaitForExit();
      process.Close();
 }
 catch (Exception ex)
 {
  this.HandleError(ex);
 }
 return outputFileName;
}

GetDecryptedFileName() just provides a name for the resulting decrypted file - it's implementation is not important. Basically, just lop the ".gpg" extension off the end of the encrypted file. The method returns the decrypted file name for further processing; again, this isn't important, and simply suited the purpose at hand.

The interesting stuff: notice we call up the Windows Command EXE using System.Diagnostics.ProcessStartInfo. The working directory is where the GnuPG application (EXE) and the public and private key files are stored.

The tricky part is passing the "secret" passphrase and options and commands to the gpg.exe process via cmd.exe. This is done through System.Diagnostics.Process.StandardInput. Essentially, you are spawning a command window and feeding it something like:

C:\> echo my passphrase goes here| gpg.exe --passphrase-fd 0 
     -o "myDecryptedOutputFileName" --decrypt "myEncryptedFileName"

Problem solved! Note the security issues with having your private key passphrase used in an application like this - that's your issue! Not a big problem for our situation.

Points of interest

Notice the "-o" option? Don't use "-output", it won't work. Also notice how we build the whole command in "sCommandLine" and pass this variable to WriteLine? Also important. For some reason, building this directly in StandardInput.WriteLine() doesn't work either - probably the escape characters in C#.

Hope that helps you avoid the frustrations we went through in coming up with this solution!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Kurt Mang
Web Developer ShakingHand Software / Web / Mobile
Canada Canada
I've been making web sites and such on the .NET platform since 2001. I suppose I specialise in Microsoft technologies.

Comments and Discussions

 
QuestionWhere is the input path? PinmemberMember 1014727529-Apr-14 5:19 
QuestionWhen we used above code then it ask me for passphrase Pinmembervinodpatidar29-Apr-13 0:00 
AnswerRe: When we used above code then it ask me for passphrase Pinmembervinodpatidar2-May-13 4:46 
Questionneed an help for encrypting file Pinmemberkumaran_vr11-Nov-11 5:33 
QuestionProblem with binary file (.xls) to be specific PinmemberMark Ashcroft27-Jun-11 1:37 
QuestionNothing really happens Pinmemberpenglund12-Jan-10 2:54 
AnswerRe: Nothing really happens Pinmembervenkatpv22-Jan-11 3:15 
Generalnew version of GnuPG [modified] PinmemberLenaBr30-Nov-09 8:49 
Generalpassphrase passing in PinmemberAWdrius12-Nov-09 0:17 
GeneralGreat, thanks! PinmemberFionaBWF6-Nov-09 1:11 
QuestionGPG Decrypt Not Work with ASP.Net [modified] PinmemberMember 40972617-Aug-09 19:53 
AnswerRe: GPG Decrypt Not Work with ASP.Net Pinmemberjwooley27-Oct-09 3:57 
GeneralGreat this is perfect thank you Pinmemberpaymeman12-Mar-09 2:15 
Answer“Notice the "-o" option? Don't use "-output", it won't work.” Pinmemberbabaa7-Mar-08 3:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 11 Dec 2007
Article Copyright 2007 by Kurt Mang
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid