Hello,

I'm attempting (in C#) to encrypt a Stream object instead of using a
FileInfo object.  I have attached my source code below. Any help would be
appreciated.

Thanks!
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using System;
using System.IO;

/// Code is provided as-is, as-written. I'm not an expert in cryptography, and 
I don't plan
/// on releasing updates. Please review prior to using in anything critical.
/// Steve Ledwith - st...@ledwith.org - http://ledwith.org
/// Released under GPLv3 - Please contact me if you have any questions.
namespace SPL.Crypto
{
    /// <summary>
    /// Wrapper around Bouncy Castle OpenPGP library.
    /// Bouncy documentation can be found here: 
http://www.bouncycastle.org/docs/pgdocs1.6/index.html
    /// Code from: 
http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx
    /// with some very minor changes.
    /// </summary>
    public class PgpEncrypt
    {
        #region Private Variables
        
        private PgpEncryptionKeys mEncryptionKeys;
        private const int bufferSize = 0x10000; // should always be power of 2 
        
        #endregion

        #region Public Methods
        /// <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.");
            }

            mEncryptionKeys = 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);
                        }
                    }
                }
            }
        }

        public void EncryptAndSignStream(Stream outputStream, Stream inStream)
        {
            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 = 
chainLiteralOutStream(compressedOut, inStream))
                    {
                        //using (FileStream inputFile = inStream.OpenRead())
                        //{
                        //    writeOutputAndSign(compressedOut, literalOut, 
inputFile, signatureGenerator);
                        //}
                        writeOutputAndSignStream(compressedOut, literalOut, 
inStream, signatureGenerator);
                    }
                }
            }
        }
       
        #endregion

        #region Private Methods
        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(mEncryptionKeys.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 = 
mEncryptionKeys.SecretKey.PublicKey.Algorithm;
            PgpSignatureGenerator pgpSignatureGenerator = new 
PgpSignatureGenerator(tag, HashAlgorithmTag.Sha1);
            pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument, 
mEncryptionKeys.PrivateKey);

            foreach (string userId in 
mEncryptionKeys.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;
        }

        private static void writeOutputAndSignStream(Stream compressedOut, 
Stream literalOut, Stream inStream, PgpSignatureGenerator signatureGenerator)
        {
            int length = 0;
            byte[] buf = new byte[bufferSize];

            while ((length = inStream.Read(buf, 0, buf.Length)) > 0)
            {
                literalOut.Write(buf, 0, length);
                signatureGenerator.Update(buf, 0, length);
            }

            signatureGenerator.Generate().Encode(compressedOut);
        }
        private static Stream chainLiteralOutStream(Stream compressedOut, 
Stream inStream)
        {
            PgpLiteralDataGenerator pgpLiteralDataGenerator = new 
PgpLiteralDataGenerator();
            return pgpLiteralDataGenerator.Open(compressedOut, 
PgpLiteralData.Binary, "filename", DateTime.Now, ReadFully(inStream));
        }


        public static byte[] ReadFully(Stream input)
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }
        #endregion
    }
}
using Org.BouncyCastle.Bcpg.OpenPgp;
using System;
using System.IO;
using System.Linq;
using System.Text;

/// Code is provided as-is, as-written. I'm not an expert in cryptography, and 
I don't plan
/// on releasing updates. Please review prior to using in anything critical.
/// Steve Ledwith - st...@ledwith.org - http://ledwith.org
/// Released under GPLv3 - Please contact me if you have any questions.
namespace SPL.Crypto
{
    public class PgpEncryptionKeys
    {
        #region Public Methods
        public PgpPublicKey PublicKey { get; private set; }
        public PgpPrivateKey PrivateKey { get; private set; }
        public PgpSecretKey SecretKey { get; private set; }

        /// <summary>
        /// Initializes a new instance of the EncryptionKeys class.
        /// Two keys are required to encrypt and sign data. Your private key 
and the recipients public key.
        /// The data is encrypted with the recipients public key and signed 
with your private key.
        /// </summary>
        /// <param name="publicKeyPath">The key used to encrypt the data</param>
        /// <param name="privateKeyPath">The key used to sign the data.</param>
        /// <param name="passPhrase">The (your) password required to access the 
private key</param>
        /// <exception cref="ArgumentException">Public key not found. Private 
key not found. Missing password</exception>
        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);
        }

        #endregion

        #region Private Methods

        #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.");
        }

        /// <summary>
        /// Return the first key we can use to encrypt.
        /// Note: A file can contain multiple keys (stored in "key rings")
        /// </summary>
        private PgpSecretKey getFirstSecretKey(PgpSecretKeyRingBundle 
secretKeyRingBundle)
        {
            foreach (PgpSecretKeyRing kRing in 
secretKeyRingBundle.GetKeyRings())
            {
                // Note: You may need to use something other than the first key
                //  in your key ring. Keep that in mind. 
                // ex: .Where(k => !k.IsSigningKey)
                var a = kRing.GetSecretKeys();

                PgpSecretKey key = kRing.GetSecretKeys()
                    .Cast<PgpSecretKey>()
                    .Where(k => k.IsSigningKey)
                    //.Where(k => !k.IsSigningKey)
                    .FirstOrDefault();

                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))
                {
                    try
                    {
                        PgpPublicKeyRingBundle publicKeyRingBundle = new 
PgpPublicKeyRingBundle(inputStream);
                        PgpPublicKey foundKey = 
getFirstPublicKey(publicKeyRingBundle);

                        if (foundKey != null)
                        {
                            return foundKey;
                        }
                    }
                    catch (Exception)
                    {
                        throw new ArgumentException("There was a problem with 
the public key ring.");
                    }
                }
            }
            throw new ArgumentException("No encryption key found in public key 
ring.");
        }

        private PgpPublicKey getFirstPublicKey(PgpPublicKeyRingBundle 
publicKeyRingBundle)
        {
            foreach (PgpPublicKeyRing kRing in 
publicKeyRingBundle.GetKeyRings())
            {
                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

        #endregion
    }
}

Reply via email to