15 October 2015

PGP encryption/decryption of files in .NET

In one of my projects, we had requirement of encrypting and decrypting files using the standard PGP (Pretty good privacy) algorithm. 

Approach

There are no built-in implementations of PGP encryption/decryption algorithms in .NET. Hence we used a third party open source DLL (BouncyCastle.Crypto.dll) from Bouncy-Castle that provided the implementation of PGP algorithm. This DLL was used after taking a formal approval from Tools-Group.

The DLL provides basic classes and methods for performing encryption/decryption which are a bit complex to understand and requires a lot of plumbing code to be usable in the project.

Hence we created a wrapper class around this DLL which provides two simple methods for encryption and decryption. This class has all the plumbing code required for using the PGP encryption/decryption functionality.

PGP Encryption/Decryption

The PGP encryption algorithm works on the basic principle of public-private key pairs. The public key is with the person who wants to encrypt the file. The private key is with the person who wants to decrypt the file. While the public key is shared with everyone, the private key is kept secret.


Implementation

We need to first add the BouncyCastle.Crypto.dll in our project.
We created a class (PGPEncryptDecrypt.cs) which acted as a wrapper around the BouncyCastle.Crypto.dll.

The class performs following tasks:-

  • Encrypt a file using PGP
  • Decrypt a file using PGP


PGP Keys

Both public and private keys are kept in separate files with “.pgp” extension. It is a simple plain text file where key is stored in encrypted format. These keys can be generated using various tools available in market viz GPG, WSFTP Professional, PGP etc.  In our project we have used WSFTP Professional to generate PGP keys.

While generating PGP keys, the tools ask for following information:-

  • Name
  • Email
  • Pass-phrase

To use the private key file, we need a pass-phrase. This pass-phrase ensures that even if someone gets hold on the private key file, they will not be able to decrypt the target file unless they know the pass-phrase as well.


Sample Code

Encrypt file

The encryption of file is doing by calling function “Encrypt” in the wrapper class. This function takes following input parameters –

  1. filePath – Path of file to be encrypted along with file name
  2. publicKeyFile – Path of public key file.
  3. pathToSaveFile – Path where encrypted file should be saved

The encrypted file is saved with a “.pgp” extension.

/// <summary>
/// Method to encrypt a file using a public key file
/// </summary>
/// <param name=”filePath”>The path of the file to be encrypted</param>
/// <param name=”publicKeyFile”>The path of the public key file</param>
/// <param name=”pathToSaveFile”>The path where encrypted file will be saved</param>
public string Encrypt(string filePath, string publicKeyFile, string pathToSaveFile)
{
    Stream keyIn, fos;

    keyIn = File.OpenRead(publicKeyFile);

    string[] fileSplit = filePath.Split(‘\\’);

    string fileName = fileSplit[fileSplit.Length – 1];

    fos = File.Create(pathToSaveFile + fileName + “.pgp”);

    EncryptFile(fos, filePath, ReadPublicKey(keyIn), true, true);

    keyIn.Close();

    fos.Close();

    return fileName + “.pgp”;

}

Decrypt file

The decryption of file is done using the “Decrypt” function in wrapper class. This function takes following input parameters:-

  1. filePath – Path of file to be decrypted along with file name.
  2. privateKeyFile – Path of private key file.
  3. passphrase – The secret pass-phrase which will be used to open the private key.
  4. pathToSaveFile – Path where decrypted file should be saved.

/// <summary>
/// Method to decrypt a file using a private key and a pass-phrase
/// </summary>
/// <param name="filePath">Path of file to be decrypted</param>
/// <param name="privateKeyFile">Path of private key file</param>
/// <param name="passPhrase">Pass phrase to decrypt file </param>
/// <param name="pathToSaveFile">Path to store the decrypted file</param>
public string Decrypt(string filePath, string privateKeyFile, string passPhrase, string pathToSaveFile)
{

    Stream fin = File.OpenRead(filePath);

    Stream keyIn = File.OpenRead(privateKeyFile);

    string decryptedFileName = DecryptFile(fin,
                                  keyIn,
                                  passPhrase.ToCharArray(),
                                  new FileInfo(filePath).Name + ".out",
                                  pathToSaveFile);

    fin.Close();

    keyIn.Close();

    return decryptedFileName;

}


Sample function calls

How to call Encrypt function:-

PGPEncryptDecrypt pgp = new PGPEncryptDecrypt();
string filePath = @"C:\SampleFile.doc";
string pathToSaveFile = @"C:\";
string encryptedFileName = string.Empty;
string publicKeyFile = @"C:\PGPKeys\PublicKey.pgp";

encryptedFileName = pgp.Encrypt(filePath, publicKeyFile, pathToSaveFile);

How to call Decrypt function

PGPEncryptDecrypt pgp = new PGPEncryptDecrypt();
string encryptedfilePath = @"C:\SampleFile.doc.pgp";
string pathToSaveFile = @"C:\";
string decryptedFileName = string.Empty;
string privateKeyFile = @"C:\PGPKeys\PrivateKey.pgp";
string passPhrase = "<Sample pass phrase>";

encryptedFileName = pgp.Decrypt(encryptedfilePath, privateKeyFile, passPhrase, pathToSaveFile);

Advantages

The class file wraps the intricacies of BouncyCastle.Crypto.dll and provides simple interface which can be used to perform PGP encryption/decryption.

2 comments:

Anonymous said...

Where is EncryptFile method?

Ganga said...

Please provide the complete source code?