I made a simple project to decrypt a pgp message using bouncycastle.
public void Decrypt(Stream encrypted_stream, string output_path)
{
encrypted_stream = PgpUtilities.GetDecoderStream(encrypted_stream);
PgpEncryptedDataList encrypted_data_list;
PgpObjectFactory pgp_factory = new PgpObjectFactory(encrypted_stream);
PgpObject pgp_object = pgp_factory.NextPgpObject();
if (pgp_object is PgpEncryptedDataList)
{
encrypted_data_list = (PgpEncryptedDataList)pgp_object;
}
else
{
encrypted_data_list = (PgpEncryptedDataList)pgp_factory.NextPgpObject();
}
PgpPrivateKey private_key = m_PGPKeys.m_PGPPrivateKey;
PgpPublicKeyEncryptedData public_encrypted_data = null;
IEnumerable encryptedDataObjects = encrypted_data_list.GetEncryptedDataObjects();
foreach (PgpPublicKeyEncryptedData pked in encrypted_data_list.GetEncryptedDataObjects())
{
if (private_key != null)
{
public_encrypted_data = pked;
break;
}
}
Stream clear_stream = public_encrypted_data.GetDataStream(private_key);
PgpObjectFactory plain_factory = new PgpObjectFactory(clear_stream);
PgpObject message = plain_factory.NextPgpObject();
if (message is PgpCompressedData)
{
PgpObjectFactory compressed_data_factory_object = HandleCompressedPGPData(ref message);
if (message is PgpOnePassSignatureList)
{
message = HandleOnePassSingnatureList(output_path, message, compressed_data_factory_object);
}
}
PgpLiteralData literal_data = (PgpLiteralData)message;
Stream output_stream = File.Create(@"C:\PGP\Result7");
Stream unencrypted_stream = literal_data.GetInputStream();
Streams.PipeAll(unencrypted_stream, output_stream);
}
private static PgpObject HandleOnePassSingnatureList(string output_path, PgpObject message, PgpObjectFactory compressed_data_factory_object)
{
message = compressed_data_factory_object.NextPgpObject();
// Literal Data packet contains the body of a message; data that is
//not to be further interpreted.
PgpLiteralData signature_literal_data = null;
signature_literal_data = (PgpLiteralData)message;
Stream signature_output_stream = File.Create(output_path + "\\" + signature_literal_data.FileName);
Stream unencrypted_signature_stream = signature_literal_data.GetInputStream();
Streams.PipeAll(unencrypted_signature_stream, signature_output_stream);
return message;
}
private static PgpObjectFactory HandleCompressedPGPData(ref PgpObject message)
{
PgpCompressedData compressed_data = (PgpCompressedData)message;
Stream compressed_data_in = compressed_data.GetDataStream();
PgpObjectFactory compressed_data_factory_object = new PgpObjectFactory(compressed_data_in);
message = compressed_data_factory_object.NextPgpObject();
return compressed_data_factory_object;
}
you need to create PgpKeys
class to handle the Pgp public and private key from key ring. like this
class PGPKeys
{
private long m_KeyId;
private string m_PrivateKeyPath;
private string m_PublicKeypath;
private string m_Password;
public PgpPublicKey m_PGPPublicKey { get; private set; }
public PgpPrivateKey m_PGPPrivateKey { get; private set; }
public PgpSecretKey m_PGPSecretKey { get; private set; }
public PGPKeys(string public_key_path, string private_key_path, string password, long key_id)
{
if (!File.Exists(public_key_path))
throw new ArgumentNullException("Could not find the public key at" + public_key_path);
if (!File.Exists(private_key_path))
throw new ArgumentNullException("Could not find the public key at" + private_key_path);
if (String.IsNullOrEmpty(password))
throw new ArgumentNullException("The password must not be null");
if (key_id == 0)
throw new ArgumentNullException("The password must not be null");
m_KeyId = key_id;
m_PGPPublicKey = GetPublicKey(public_key_path);
m_PGPPrivateKey = GetPrivateKey(password, private_key_path);
}
private PgpPrivateKey GetPrivateKey(string password, string private_key_path)
{
PgpSecretKey secret_key = GetSecretKey(private_key_path);
PgpPrivateKey private_key = secret_key.ExtractPrivateKey(password.ToCharArray());
if (private_key == null)
return null;
return private_key;
}
private PgpSecretKey GetSecretKey(string private_key_path)
{
PgpSecretKey secret_key = null;
using (Stream keyin = File.OpenRead(private_key_path))
{
using (Stream private_key_Stream = PgpUtilities.GetDecoderStream(keyin))
{
PgpSecretKeyRingBundle secret_key_ring_bundle = new PgpSecretKeyRingBundle(private_key_Stream);
secret_key = GetLastSecretKey(secret_key_ring_bundle);
}
}
return secret_key;
}
private PgpPublicKey GetPublicKey(string public_key_path)
{
PgpPublicKey public_key = null;
using (Stream keyin = File.OpenRead(public_key_path))
{
using (Stream public_key_stream = PgpUtilities.GetDecoderStream(keyin))
{
PgpPublicKeyRingBundle public_key_bundle = new PgpPublicKeyRingBundle(public_key_stream);
foreach (PgpPublicKeyRing public_key_ring in public_key_bundle.GetKeyRings())
{
foreach (PgpPublicKey key in public_key_ring.GetPublicKeys())
{
long modified_key_id = key.KeyId & 0x00000000FFFFFFFF;
if (modified_key_id == m_KeyId)
{
public_key = key;
break;
}
}
}
if (public_key == null)
throw new Exception("The public key value is null");
}
return public_key;
}
}
private PgpSecretKey GetLastSecretKey(PgpSecretKeyRingBundle secret_key_ring_bundle)
{
IEnumerable pgpKeyRings = secret_key_ring_bundle.GetKeyRings();
return (from PgpSecretKeyRing kring in secret_key_ring_bundle.GetKeyRings()
select kring.GetSecretKeys().Cast<PgpSecretKey>().
LastOrDefault(k => k.IsSigningKey)).LastOrDefault(key => key != null);
}
}
if you need any explanation, just let me know.