I have a requirment to send PGP Encrypted CSV Files to SFTP and i know nothing aboutr PGP. After a lot of research I could find following code on internet using 'Bouncy Castle' Library. The code seems gogod but does not work for me given my inexperience in PGP. Please help me in finding right values for:
- publicKeyFileName
- privateKeyFileName
- pasPhrase
Below is my code:
namespace PgpEncryption
{
class Program
{
public static void Main()
{
EncryptAndSign();
}
private static void EncryptAndSign()
{
string publicKeyFileName = "";
string privateKeyFileName = "";
string pasPhrase = "";
PgpEncryptionKeys encryptionKeys
= new PgpEncryptionKeys(publicKeyFileName, privateKeyFileName, pasPhrase);
PgpEncrypt encrypter = new PgpEncrypt(encryptionKeys);
string encryptedFileName = "";
using (Stream outputStream = File.Create(encryptedFileName))
{
string fileToEncrypt = "";
encrypter.EncryptAndSign(outputStream, new FileInfo(fileToEncrypt));
}
}
}
}
public class PgpEncryptionKeys
{
public PgpEncryptionKeys(string publicKeyPath, string privateKeyPath, string passPhrase)
{
if (!File.Exists(publicKeyPath))
throw new ArgumentException("Public key file not found", "publicKeyPath");
if (!File.Exists(privateKeyPath))
throw new ArgumentException("Private key file not found", "privateKeyPath");
if (String.IsNullOrEmpty(passPhrase))
throw new ArgumentException("passPhrase is null or empty.", "passPhrase");
PublicKey = ReadPublicKey(publicKeyPath);
SecretKey = ReadSecretKey(privateKeyPath);
PrivateKey = ReadPrivateKey(passPhrase);
}
#region Secret Key
private PgpSecretKey ReadSecretKey(string privateKeyPath)
{
using (Stream keyIn = File.OpenRead(privateKeyPath))
using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
if (foundKey != null)
return foundKey;
}
throw new ArgumentException("Can't find signing key in key ring.");
}
private PgpSecretKey GetFirstSecretKey(PgpSecretKeyRingBundle secretKeyRingBundle)
{
foreach (PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings())
{
PgpSecretKey key = (PgpSecretKey)kRing.GetSecretKeys();
if (key != null)
return key;
}
return null;
}
#endregion
#region Public Key
private PgpPublicKey ReadPublicKey(string publicKeyPath)
{
using (Stream keyIn = File.OpenRead(publicKeyPath))
using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpPublicKeyRingBundle publicKeyRingBundle = new PgpPublicKeyRingBundle(inputStream);
PgpPublicKey foundKey = GetFirstPublicKey(publicKeyRingBundle);
if (foundKey != null)
return foundKey;
}
throw new ArgumentException("No encryption key found in public key ring.");
}
private PgpPublicKey GetFirstPublicKey(PgpPublicKeyRingBundle publicKeyRingBundle)
{
foreach (PgpPublicKeyRing kRing in publicKeyRingBundle.GetKeyRings())
{
PgpPublicKey key = (PgpPublicKey)kRing.GetPublicKeys();
//PgpPublicKey key = kRing.GetPublicKeys()
//.Cast<PgpPublicKey>()
// .Where(k => k.IsEncryptionKey)
// .FirstOrDefault();
if (key != null)
return key;
}
return null;
}
#endregion
#region Private Key
private PgpPrivateKey ReadPrivateKey(string passPhrase)
{
PgpPrivateKey privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());
if (privateKey != null)
return privateKey;
throw new ArgumentException("No private key found in secret key.");
}
#endregion
}
public class PgpEncrypt
{
private PgpEncryptionKeys m_encryptionKeys;
private const int BufferSize = 0x10000; // should always be power of 2
/// <summary>
/// Instantiate a new PgpEncrypt class with initialized PgpEncryptionKeys.
/// </summary>
/// <param name="encryptionKeys"></param>
/// <exception cref="ArgumentNullException">encryptionKeys is null</exception>
public PgpEncrypt(PgpEncryptionKeys encryptionKeys)
{
if (encryptionKeys == null)
throw new ArgumentNullException("encryptionKeys", "encryptionKeys is null.");
m_encryptionKeys = encryptionKeys;
}
/// <summary>
/// Encrypt and sign the file pointed to by unencryptedFileInfo and
/// write the encrypted content to outputStream.
/// </summary>
/// <param name="outputStream">The stream that will contain the
/// encrypted data when this method returns.</param>
/// <param name="fileName">FileInfo of the file to encrypt</param>
public void EncryptAndSign(Stream outputStream, FileInfo unencryptedFileInfo)
{
if (outputStream == null)
throw new ArgumentNullException("outputStream", "outputStream is null.");
if (unencryptedFileInfo == null)
throw new ArgumentNullException("unencryptedFileInfo", "unencryptedFileInfo is null.");
if (!File.Exists(unencryptedFileInfo.FullName))
throw new ArgumentException("File to encrypt not found.");
using (Stream encryptedOut = ChainEncryptedOut(outputStream))
using (Stream compressedOut = ChainCompressedOut(encryptedOut))
{
PgpSignatureGenerator signatureGenerator = InitSignatureGenerator compressedOut);
using (Stream literalOut = ChainLiteralOut(compressedOut, unencryptedFileInfo))
using (FileStream inputFile = unencryptedFileInfo.OpenRead())
{
WriteOutputAndSign(compressedOut, literalOut, inputFile, signatureGenerator);
}
}
}
private static void WriteOutputAndSign(Stream compressedOut,Stream literalOut,FileStream inputFile,PgpSignatureGenerator signatureGenerator)
{
int length = 0;
byte[] buf = new byte[BufferSize];
while ((length = inputFile.Read(buf, 0, buf.Length)) > 0)
{
literalOut.Write(buf, 0, length);
signatureGenerator.Update(buf, 0, length);
}
signatureGenerator.Generate().Encode(compressedOut);
}
private Stream ChainEncryptedOut(Stream outputStream)
{
PgpEncryptedDataGenerator encryptedDataGenerator;
encryptedDataGenerator =
new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.TripleDes,
new SecureRandom());
encryptedDataGenerator.AddMethod(m_encryptionKeys.PublicKey);
return encryptedDataGenerator.Open(outputStream, new byte[BufferSize]);
}
private static Stream ChainCompressedOut(Stream encryptedOut)
{
PgpCompressedDataGenerator compressedDataGenerator =
new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
return compressedDataGenerator.Open(encryptedOut);
}
private static Stream ChainLiteralOut(Stream compressedOut, FileInfo file)
{
PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator();
return pgpLiteralDataGenerator.Open(compressedOut, PgpLiteralData.Binary, file);
}
private PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut)
{
const bool IsCritical = false;
const bool IsNested = false;
PublicKeyAlgorithmTag tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm;
PgpSignatureGenerator pgpSignatureGenerator =
new PgpSignatureGenerator(tag, HashAlgorithmTag.Sha1);
pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument, m_encryptionKeys.PrivateKey);
foreach (string userId in m_encryptionKeys.SecretKey.PublicKey.GetUserIds())
{
PgpSignatureSubpacketGenerator subPacketGenerator =
new PgpSignatureSubpacketGenerator();
subPacketGenerator.SetSignerUserId(IsCritical, userId);
pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate());
// Just the first one!
break;
}
pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut);
return pgpSignatureGenerator;
}
}