简体   繁体   中英

How to decrypt pgp file with bouncycastle using c# using the public key

I am looking for a code sample that will show me how to decrypt a pgp file with the public key using bouncy castle. I have code that will decrypt a file that has been encrypted with the key I supply to the user, but for I only have the public key from the client and my same code wont work.

So any help on this would be appreciated. :)

JD

You cannot decrypt using the public key , at least not without sophisticated attacks on the crypto schemes, which hopefully do not exist for the algorithms in use, as they would allow anybody to decrypt encrypted messages. The idea behind asymmetric (public/private key) encryption is preventing decryption using the public key, which can be arbitrarily shared (it can be public) while only the holder of the private key can decrypt.

Principally for some asymmetric algorithms like RSA, public and private key pairs are interchangeable, but then the would have to use the private key to encrypt, so that the public key can be used to decrypt , which just switched the definition of the keys. This behavior is kind of exploited for digital signatures, where the message (usually only a hash sum of the message) is encrypted by the private key. If the message/hash sum can be decrypted using the public key, it must have been encrypted with the private key -- as nobody but the key's owner could have been using it.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM