DCSIMG
PGP Zip Encrypted Files With C# - .NET Geek

.NET Geek

"It is upon the Trunk that a gentleman works" - Confucius

PGP Zip Encrypted Files With C#

On a recent project here at Renaissance, we needed to send files over FTP to some third party vendor. One of the requirements was that the files had to be encrypted using PGP (Pretty Good Privacy). After some research we decided to use Bouncy Castle. Bouncy Castle is an open source C# implementation of the OpenPGP standard. It is available in Java as well.
An additional requirement was that the PGP Encrypted files needed to be signed as well.

If you have no background in cryptology or PGP and this sounds like gibberish, here’s a short simplified background on symmetric key encryption.

To share PGP encrypted files the sender and recipient both need two keys. One public and one private. The sender encrypts the file to send with the recipients public key and sign with his private key. Both parties then exchange public keys. Each party can decrypt using its own private key and it can verify who sent the file using the senders public key.

If this still sounds gibberish, I found this illustration on the LinomaSoftware site a good visual explanation. (never used it, just searched Google for PGP image)

With that out of the way, how hard can it be to encrypt and sign a file? Not very hard, but far too much code to write. We found a few samples online, but nothing I felt comfortable to use in our codebase. Credits to John Opincar who published a post on single pass encryption and signing. We used the blog post of his, the Bouncy test suites and a some trial and failure to get it working.

One of the issues with all the sample code out there, is that there are so many responsibilities squeezed together that unless you know what the code is doing beforehand, it is hard to grasp. It was to me at least. That might be partially related to me having no significant background in cryptology or PGP.

Lets see some code. No matter if I’m doing TDD or not, I always try to write the client code before the API. That way I shape the API from the point of view of the consuming code and avoid surprising and clunky interfaces later. I wanted the calling code to look like this.

private static void EncryptAndSign()

{

    PgpEncryptionKeys encryptionKeys = new PgpEncryptionKeys(

                                   PublicKeyFileName, PrivateKeyFileName, "PasswordOfMyPrivateKey");

    PgpEncrypt encrypter = new PgpEncrypt(encryptionKeys);

    using (Stream outputStream = File.Create(EncryptedFileName))

    {

        encrypter.EncryptAndSign(outputStream, new FileInfo(FileToEncrypt));

    }

}

From the sample code above you can see that we have separated Key management code from the actual encryption code. The PgpEncryptionKeys class instantiates and deals with the intricacies of key management. The PgpEncrypt class does this actual encryption. There were two reasons for this separation. The first is that key management is a separate concern conceptually. Another is that while we currently point to the location of the key files, we might want to change that in the future. I want to be able to change the way we instantiate the keys without touching the encryption code. No efforts were made at this point to create interfaces and/or abstract classes for evolution or extensibility. We’ll do that when/if we’ll need it.

Next we will have a look at the actual implementation. I will not walk through and explain all the code. We tried to make the code as self explanatory as possible. However, if you have no other background related to encryption and PGP besides this blog post, you should probably spend a few hours reading up on that before considering using this code. Treat this code As-Is with no commitment on my side to keep it up-to-date with bug fixes and improvements.

using System;

using System.IO;

using System.Linq;

using Org.BouncyCastle.Bcpg.OpenPgp;

namespace Renaissance.Common.Encryption

{

    public class PgpEncryptionKeys

    {

        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);

        }

        #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())

            {

                PgpSecretKey key = kRing.GetSecretKeys()

                    .Cast<PgpSecretKey>()

                    .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))

            {

                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 = 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

    }

}

As you can see from the code and comments, PGP has a concept of key rings. In other words there can be many keys. We assume a single key.

Now to the PGP encryption class

using System;

using System.IO;

using Org.BouncyCastle.Bcpg;

using Org.BouncyCastle.Bcpg.OpenPgp;

using Org.BouncyCastle.Security;

namespace Renaissance.Common.Encryption

{

    /// <summary>

    /// Wrapper around Bouncy Castle OpenPGP library.

    /// Bouncy documentation can be found here: http://www.bouncycastle.org/docs/pgdocs1.6/index.html

    /// </summary>

    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;

        }

    }

}

It should be clear from the code above, but one concept that helped understand the implementation of the Bouncy classes was that they basically just creates a pipeline of streams. We expressed these as XXX ChainXXX(innerStream){} where the ChainXXX methods take the stream to wrap and returns the wrapped stream. Encapsulating this concept into small ChainXXX classes made the resulting code much more readable IMHO.

Comments, corrections and improvements are welcome as always…

kick it on DotNetKicks.com
Posted: Jan 23 2009, 12:14 PM by Kim | with 60 comment(s)
תגים:, , , ,

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# January 23, 2009 12:18 PM

LaPo said:

Hi,

thank you for your article. You wrote about to encrypt, but do you have also an example from decrypt an pgp file? You divide it with me?

Thanks...

Bye Ralf

# January 31, 2009 3:27 PM

Kim said:

No I don't since we only had to send data. I have been playing with the thought of expanding the code above with some more functionality.

I thought of supporting at least:

1) Encoding (more flexible than the one above) e.g including arbitrary text and not only files.

2) Decode

3) Key management.

4) ???

If there's enough demand I'll try to find the time to expand on this.

Please leave a comment if you would like this and/or any feature you would like to see.

# January 31, 2009 9:10 PM

LaPo said:

Hello Kim,

thank's for your answer.

It will be fine, if you expand your code sample.

I have the problem, that i'm became an gpg file and i have to decrypt this file in a DotNet program.  I have search about this in the web, with little succeed. Your blog was the only...

Bye

Ralf

# February 2, 2009 12:01 PM

Firoz Ozman said:

Hi Kim

This code so useful as I am working on exactly same stuff. Everything works fine except the last step where I am trying to convert the OutputStream to a Memorystream to be used inside the Pipeline. I get System.ObjectDisposedException: Cannot access a closed file.

Please help as I need figure this out soon.

Please mail me at firozozman@gmail.com

Thanks

Firoz Ozman

# February 21, 2009 3:38 AM

Firoz Ozman said:

Kim,

No worries.. I figured out it was coz of the test windows app I was using to test. I was accessing a file from Windows App and sending across to encrypt/sign.

Hey I have a complete version of this ready.

It does Encrypt/Decrypt and Encrypt with Sign. I will post this soon on http://www.firozozman.com.

Take care

Firoz Ozman

# February 21, 2009 5:59 AM

.NET Geek said:

I can’t decide what I think about the following implementation so I decided to throw it out here. Any

# February 23, 2009 11:35 PM

Girish said:

Do you have the decrypted method too?

# February 27, 2009 5:03 AM

Girish said:

I got the decrypt method working, used the one that is available in the BouncyCastle sample and wrote a wrapper around it. Works with both signed and unsigned. Shoot me a email if you want the code

girishSIXSIX @ h0tma1l . c0m      

Tried to obfusicate it a little bit, replace SIX SIX with the number SIXTYSIX the 0's are o's and the 1 is a i

# February 27, 2009 6:22 PM

Tracy said:

Thank you for posting this.  I am still trying to figure how this works.  I had a dll that required keyid and no passPhrase but it encypts file in Unix format.  We need PC format.  Can you point me a direction on how to use bouncy castle without using passPhrase but use a keyid instead of getFirstPublicKey?

Thank you.

# April 17, 2009 2:19 AM

pavankumar said:

thnx for the code you ve given.but for pgpencryptionkeys you are passing the files right so can you please specify the file format.

# May 6, 2009 4:03 PM

pavankumar said:

can u please provide code for decryption.

# May 8, 2009 1:38 PM

Chris Porter said:

Thank you very much for this resource. My client was looking for the exact same functionality (file -> encryption -> ftp) so this was a perfect fit. I used the code almost completely as-is and it worked great. This code was combined with a small command line utility that supported the FTP side of things. We haven't done a full end-to-end test yet but I was successful in my own test environment.

I will post in the future with the end-to-end results.

# May 11, 2009 10:54 PM

Chris Porter said:

Its been awhile since I have posted my initial comment but I wanted to give a follow-up.  The code here worked with very few changes.  After pretty extensive testing, I found nothing wrong with my implementation of this code or the BouncyCastle.Crypto library.  I did have problems with the FTP library I'm using but that's a different topic.

Thanks Kim!!

# July 29, 2009 8:05 PM

Ian Patrick Hughes said:

I used the C# Bouncy library for a PGP project over a year ago. Now that I have to revisit it, I am refreshing myself and see, lo and behold, I went down a very similar path. That's reassuring if nothing else.

On the FTP side of things, what problems have you encountered? I have not found any issues using WinSCP in my managed code.

# November 4, 2009 7:54 PM

Kim said:

We have not encountered any issues with FTP so far. (running in production for a few months)

The FTP upload is part of the application and we use the .NET FtpWebRequest. Most of the files are < 100MB and transferred over a high bandwidth line. In short, no issues...

# November 5, 2009 12:43 AM

Tarek said:

How can I get data from compressedOut (WrappedGeneratorStream)?

It's still empty !

# November 5, 2009 4:13 PM

Kim said:

I'm not sure I understand your question. If you want to retrieve the original content (as it was before encryption) you can look at the samples included with Bouncy. There are many samples online.

I haven't looked at the below link thoroughly, but it should get you started.

karym6.blogspot.com/.../pgp-decryption-with-c.html

# November 5, 2009 7:47 PM

Tarek said:

Thanks Kim for you reply.

My question is when I run your "EncryptAndSign(..)" function, the stream compressedout is still empty !

Is it a pb with my keys, please see below my key generator function :

private static void ExportKeyPair(Stream secretOut, Stream publicOut,

           AsymmetricKeyParameter publicKey, AsymmetricKeyParameter privateKey,

           string identity, char[] passPhrase, bool armor)

       {            

           if (armor)

           {  

               secretOut = new ArmoredOutputStream(secretOut);

           }            

           PgpSecretKey secretKey = new PgpSecretKey(PgpSignature.DefaultCertification,

               PublicKeyAlgorithmTag.RsaGeneral, publicKey, privateKey, DateTime.Now,

               identity, SymmetricKeyAlgorithmTag.TripleDes, passPhrase, null, null,

               new SecureRandom());            

           secretKey.Encode(secretOut);

           secretOut.Close();            

           if (armor)

           {        

               publicOut = new ArmoredOutputStream(publicOut);

           }            

           PgpPublicKey key = secretKey.PublicKey;

           key.Encode(publicOut);

           publicOut.Close();

       }

       public static void GenerateKey(string username, string password, string keyStoreUrl)

       {

           IAsymmetricCipherKeyPairGenerator kpg = new RsaKeyPairGenerator();

           kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(), 1024, 8));

           AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

           FileStream out1 =

               new FileInfo(string.Format("{0}secret.asc", keyStoreUrl)).OpenWrite();

           FileStream out2 = new FileInfo(string.Format("{0}pub.asc", keyStoreUrl)).OpenWrite();

           ExportKeyPair(out1, out2, kp.Public, kp.Private, username, password.ToCharArray(), true);

       }

Thanks

# November 6, 2009 8:39 AM

Kim said:

Possibly, but it's hard for me to say without the source. Make sure the literal stream is being written to in WriteOutputAndSign(). What probably would be most helpful, is to run your code with the Bouncy code added as a project reference. Then you can step into

signatureGenerator.Generate().Encode(compressedOut);" (the last line in WriteOutputAndSign and where compressedOut is written to)

and maybe spot the problem.

# November 7, 2009 8:59 PM

Samir said:

The below definitely works..... Have tried it right now...

public static void GenerateKey(string username, string password, string keyStoreUrl)

      {

          IAsymmetricCipherKeyPairGenerator kpg = new RsaKeyPairGenerator();

          kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(), 1024, 8));

          AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

          FileStream out1 =

              new FileInfo(string.Format("{0}secret.asc", keyStoreUrl)).OpenWrite();

          FileStream out2 = new FileInfo(string.Format("{0}pub.asc", keyStoreUrl)).OpenWrite();

          ExportKeyPair(out1, out2, kp.Public, kp.Private, username, password.ToCharArray(), true);

out1.Close();

out2.Close();

      }

# April 23, 2010 10:22 PM

Mike said:

   public class PGPEncryptDecrypt

   {

       /**

       * A simple routine that opens a key ring file and loads the first available key suitable for

       * encryption.

       *

       * @param in

       * @return

       * @m_out

       * @

       */

       private static PgpPublicKey ReadPublicKey(Stream inputStream)

       {

           inputStream = PgpUtilities.GetDecoderStream(inputStream);

           PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(inputStream);

           //

           // we just loop through the collection till we find a key suitable for encryption, in the real

           // world you would probably want to be a bit smarter about this.

           //

           //

           // iterate through the key rings.

           //

           foreach (PgpPublicKeyRing kRing in pgpPub.GetKeyRings())

           {

               foreach (PgpPublicKey k in kRing.GetPublicKeys())

               {

                   if (k.IsEncryptionKey)

                   {

                       return k;

                   }

               }

           }

           throw new ArgumentException("Can't find encryption key in key ring.");

       }

       /**

       * Search a secret key ring collection for a secret key corresponding to

       * keyId if it exists.

       *

       * @param pgpSec a secret key ring collection.

       * @param keyId keyId we want.

       * @param pass passphrase to decrypt secret key with.

       * @return

       */

       private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyId, char[] pass)

       {

           PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);

           if (pgpSecKey == null)

           {

               return null;

           }

           return pgpSecKey.ExtractPrivateKey(pass);

       }

       /**

       * decrypt the passed in message stream

       */

       private static void DecryptFile(Stream inputStream, Stream keyIn, char[] passwd, string pathToSaveFile)

       {

           inputStream = PgpUtilities.GetDecoderStream(inputStream);

           try

           {

               PgpObjectFactory pgpF = new PgpObjectFactory(inputStream);

               PgpEncryptedDataList enc;

               PgpObject o = pgpF.NextPgpObject();

               //

               // the first object might be a PGP marker packet.

               //

               if (o is PgpEncryptedDataList)

               {

                   enc = (PgpEncryptedDataList)o;

               }

               else

               {

                   enc = (PgpEncryptedDataList)pgpF.NextPgpObject();

               }

               //

               // find the secret key

               //

               PgpPrivateKey sKey = null;

               PgpPublicKeyEncryptedData pbe = null;

               PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(

               PgpUtilities.GetDecoderStream(keyIn));

               foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())

               {

                   sKey = FindSecretKey(pgpSec, pked.KeyId, passwd);

                   if (sKey != null)

                   {

                       pbe = pked;

                       break;

                   }

               }

               if (sKey == null)

               {

                   throw new ArgumentException("secret key for message not found.");

               }

               Stream clear = pbe.GetDataStream(sKey);

               PgpObjectFactory plainFact = new PgpObjectFactory(clear);

               PgpObject message = plainFact.NextPgpObject();

               if (message is PgpCompressedData)

               {

                   PgpCompressedData cData = (PgpCompressedData)message;

                   PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream());

                   message = pgpFact.NextPgpObject();

               }

               if (message is PgpLiteralData)

               {

                   PgpLiteralData ld = (PgpLiteralData)message;

                   //string outFileName = ld.FileName;

                   //if (outFileName.Length == 0)

                   //{

                   //    outFileName = defaultFileName;

                   //}

                   Stream fOut = File.Create(pathToSaveFile);

                   Stream unc = ld.GetInputStream();

                   Streams.PipeAll(unc, fOut);

                   fOut.Close();

               }

               else if (message is PgpOnePassSignatureList)

               {

                   throw new PgpException("encrypted message contains a signed message - not literal data.");

               }

               else

               {

                   throw new PgpException("message is not a simple encrypted file - type unknown.");

               }

               if (pbe.IsIntegrityProtected())

               {

                   if (!pbe.Verify())

                   {

                       Console.WriteLine("message failed integrity check");

                   }

                   else

                   {

                       Console.WriteLine("message integrity check passed");

                   }

               }

               else

               {

                   Console.WriteLine("no message integrity check");

               }

           }

           catch (PgpException e)

           {

               Console.WriteLine(e);

               Exception underlyingException = e.InnerException;

               if (underlyingException != null)

               {

                   Console.WriteLine(underlyingException.Message);

                   Console.WriteLine(underlyingException.StackTrace);

               }

               System.Windows.Forms.MessageBox.Show(e.ToString());

           }

       }

       private static void EncryptFile(Stream outputStream, string fileName, PgpPublicKey encKey, bool armor, bool withIntegrityCheck)

       {

           if (armor)

           {

               outputStream = new ArmoredOutputStream(outputStream);

           }

           try

           {

               MemoryStream bOut = new MemoryStream();

               PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(

               CompressionAlgorithmTag.Zip);

               PgpUtilities.WriteFileToLiteralData(

               comData.Open(bOut),

               PgpLiteralData.Binary,

               new FileInfo(fileName));

               comData.Close();

               PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(

               SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());

               cPk.AddMethod(encKey);

               byte[] bytes = bOut.ToArray();

               Stream cOut = cPk.Open(outputStream, bytes.Length);

               cOut.Write(bytes, 0, bytes.Length);

               cOut.Close();

               if (armor)

               {

                   outputStream.Close();

               }

           }

           catch (PgpException e)

           {

               Console.WriteLine(e);

               Exception underlyingException = e.InnerException;

               if (underlyingException != null)

               {

                   Console.WriteLine(underlyingException.Message);

                   Console.WriteLine(underlyingException.StackTrace);

               }

           }

       }

       public static void Encrypt(string filePath, string publicKeyFile, string OutputFilePath)

       {

           Stream keyIn, fos;

           keyIn = File.OpenRead(publicKeyFile);

           fos = File.Create(OutputFilePath);

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

           keyIn.Close();

           fos.Close();

       }

       public static void Decrypt(string filePath, string privateKeyFile, string passPhrase, string pathToSaveFile)

       {

           Stream fin = File.OpenRead(filePath);

           Stream keyIn = File.OpenRead(privateKeyFile);

           DecryptFile(fin, keyIn, passPhrase.ToCharArray(), pathToSaveFile);

           fin.Close();

           keyIn.Close();

       }

       public static void GenerateKey(string username, string password, string keyStoreUrl)

       {

           IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");

           // new RsaKeyPairGenerator();

           kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(), 1024, 8));

           AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

           FileStream out1 = new FileInfo(string.Format("{0}_PrivateKey.txt", keyStoreUrl)).OpenWrite();

           FileStream out2 = new FileInfo(string.Format("{0}_PublicKey.txt", keyStoreUrl)).OpenWrite();

           ExportKeyPair(out1, out2, kp.Public, kp.Private, PublicKeyAlgorithmTag.RsaGeneral, SymmetricKeyAlgorithmTag.Cast5, username, password.ToCharArray(), true);

           out1.Close();

           out2.Close();

           /*

            IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");

            DsaParametersGenerator pGen = new DsaParametersGenerator();

            pGen.Init(1024, 80, new SecureRandom());

            DsaParameters dsaParams = pGen.GenerateParameters();

            DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams);

            dsaKpg.Init(kgp);

            //

            // this takes a while as the key generator has to Generate some DSA parameters

            // before it Generates the key.

            //

            AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair();

            IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");

            ElGamalParametersGenerator eGen = new ElGamalParametersGenerator();

            eGen.Init(1024,80,new SecureRandom());

            ElGamalParameters elParams = eGen.GenerateParameters();

            ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);

            elgKpg.Init(elKgp);

            //

            // this is quicker because we are using preGenerated parameters.

            //

            AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair();

            FileStream out3 = new FileInfo(string.Format("{0}_PrivateKey_ELGMAL.txt", keyStoreUrl)).OpenWrite();

            FileStream out4 = new FileInfo(string.Format("{0}_PublicKey_ELGMAL.txt", keyStoreUrl)).OpenWrite();

            ExportKeyPair(out3, out4, dsaKp, elgKp, username, password.ToCharArray(), true);

            out3.Close();

            out4.Close();

            */

       }

       private static void ExportKeyPair(

                   Stream secretOut,

                   Stream publicOut,

                   AsymmetricKeyParameter publicKey,

                   AsymmetricKeyParameter privateKey,

           PublicKeyAlgorithmTag PublicKeyAlgorithmTag,

           SymmetricKeyAlgorithmTag SymmetricKeyAlgorithmTag,

                   string identity,

                   char[] passPhrase,

                   bool armor)

       {

           if (armor)

           {

               secretOut = new ArmoredOutputStream(secretOut);

           }

           PgpSecretKey secretKey = new PgpSecretKey(

               PgpSignature.DefaultCertification,

               PublicKeyAlgorithmTag,

               publicKey,

               privateKey,

               DateTime.Now,

               identity,

               SymmetricKeyAlgorithmTag,

               passPhrase,

               null,

               null,

               new SecureRandom()

               //                ,"BC"

               );

           secretKey.Encode(secretOut);

           secretOut.Close();

           if (armor)

           {

               publicOut = new ArmoredOutputStream(publicOut);

           }

           PgpPublicKey key = secretKey.PublicKey;

           key.Encode(publicOut);

           publicOut.Close();

       }

       public void SignAndEncryptFile(string actualFileName, string embeddedFileName,

              Stream keyIn, long keyId,string OutputFileName ,

              char[] password, bool armor, bool withIntegrityCheck, PgpPublicKey encKey)

       {

           const int BUFFER_SIZE = 1 << 16; // should always be power of 2

           Stream outputStream = File.Open(OutputFileName, FileMode.Create);

           if (armor)

               outputStream = new ArmoredOutputStream(outputStream);

           // Init encrypted data generator

           PgpEncryptedDataGenerator encryptedDataGenerator =

               new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());

           encryptedDataGenerator.AddMethod(encKey);

           Stream encryptedOut = encryptedDataGenerator.Open(outputStream, new byte[BUFFER_SIZE]);

           // Init compression

           PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);

           Stream compressedOut = compressedDataGenerator.Open(encryptedOut);

           // Init signature

           PgpSecretKeyRingBundle pgpSecBundle = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));

           PgpSecretKey pgpSecKey = pgpSecBundle.GetSecretKey(keyId);

           if (pgpSecKey == null)

               throw new ArgumentException(keyId.ToString("X") + " could not be found in specified key ring bundle.", "keyId");

           PgpPrivateKey pgpPrivKey = pgpSecKey.ExtractPrivateKey(password);

           PgpSignatureGenerator signatureGenerator = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);

           signatureGenerator.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);

           foreach (string userId in pgpSecKey.PublicKey.GetUserIds())

           {

               PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();

               spGen.SetSignerUserId(false, userId);

               signatureGenerator.SetHashedSubpackets(spGen.Generate());

               // Just the first one!

               break;

           }

           signatureGenerator.GenerateOnePassVersion(false).Encode(compressedOut);

           // Create the Literal Data generator output stream

           PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator();

           FileInfo embeddedFile = new FileInfo(embeddedFileName);

           FileInfo actualFile = new FileInfo(actualFileName);

           // TODO: Use lastwritetime from source file

           Stream literalOut = literalDataGenerator.Open(compressedOut, PgpLiteralData.Binary,

               embeddedFile.Name, actualFile.LastWriteTime, new byte[BUFFER_SIZE]);

           // Open the input file

           FileStream inputStream = actualFile.OpenRead();

           byte[] buf = new byte[BUFFER_SIZE];

           int len;

           while ((len = inputStream.Read(buf, 0, buf.Length)) > 0)

           {

               literalOut.Write(buf, 0, len);

               signatureGenerator.Update(buf, 0, len);

           }

           literalOut.Close();

           literalDataGenerator.Close();

           signatureGenerator.Generate().Encode(compressedOut);

           compressedOut.Close();

           compressedDataGenerator.Close();

           encryptedOut.Close();

           encryptedDataGenerator.Close();

           inputStream.Close();

           if (armor)

               outputStream.Close();

       }

       private static void ExportKeyPair(

           Stream secretOut,

           Stream publicOut,

           AsymmetricCipherKeyPair dsaKp,

           AsymmetricCipherKeyPair elgKp,

           string identity,

           char[] passPhrase,

           bool armor)

       {

           if (armor)

           {

               secretOut = new ArmoredOutputStream(secretOut);

           }

           PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow);

           PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow);

           PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,

               identity, SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, new SecureRandom());

           keyRingGen.AddSubKey(elgKeyPair);

           keyRingGen.GenerateSecretKeyRing().Encode(secretOut);

           if (armor)

           {

               secretOut.Close();

               publicOut = new ArmoredOutputStream(publicOut);

           }

           keyRingGen.GeneratePublicKeyRing().Encode(publicOut);

           if (armor)

           {

               publicOut.Close();

           }

       }

   }

# May 5, 2010 2:11 PM

Mike said:

An Eg: public key created with this code...

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: BCPG C# v1.6.1.0

mIsES+Fg5wEEAJrkeNnXhQtG9ksqP6vCxxCHrdl32ud9mZUo3l82wr6hzHFXytxN

Zro/eSchYKtrWWpnWic20zy0vVdG4r2lqC7tc+OMdRHftqNi/97T/D0geU4G0zjV

PegwzjwUEflYZmzA5CdMIegelmKXHvN4mBzKhRrIz25pYZZUtvo+oATZAAUTtAhz

cGFyZWtoM4icBBABAgAGBQJL4VLXAAoJEEdeXuFsWFgEsicD/1M/CaK/Gh+zv/Lj

GauXRf5G6KyHSX4oLjn8xAZTVtPYxgJHmN5/JpQgcwqAfxtfgMehsEXG2RNehOCl

mabkk0caJJCg5epbuKoc6SnqrquTBX0Fi9+xuMyx8AFtXuXb0IygwOPWoHeT0IkM

/gy6isQjlDHfTHTsybb67BxgLb4C

=ZyOZ

-----END PGP PUBLIC KEY BLOCK-----

# May 7, 2010 8:56 PM

Gmc K35 K3500 Pickup Yukon Denali Xl Truck Parts, K20 Pickup Part Exhaust Manifold Discount - 1.1fh.org said:

Pingback from  Gmc K35 K3500 Pickup Yukon Denali Xl Truck Parts, K20 Pickup Part Exhaust Manifold Discount - 1.1fh.org

# May 24, 2010 2:45 PM

Dell Laptop E4300, 1999 Mercedes Benz E430 Parts Tail Light Bulbs - 202.computeronlinebingo.com said:

Pingback from  Dell Laptop E4300, 1999 Mercedes Benz E430 Parts Tail Light Bulbs - 202.computeronlinebingo.com

# May 25, 2010 9:52 AM

1988 - 2009 @ L200 Aftermarket Lw300 Saturn Sl2, Radiator 1999 Sl2 Saturn Sl1 - 336.computeronlinebingo.com said:

Pingback from  1988 - 2009 @ L200 Aftermarket Lw300 Saturn Sl2, Radiator 1999 Sl2 Saturn Sl1 - 336.computeronlinebingo.com

# May 31, 2010 10:50 PM

C# How to encrypt a data file Bouncy Castle pgp? | Webmaster Forum Archive said:

Pingback from  C# How to encrypt a data file Bouncy Castle pgp? | Webmaster Forum Archive

# June 1, 2010 7:07 PM

PGP Encryption with BouncyCastle C# causes invalid key warning on signature verification | Webmaster Forum Archive said:

Pingback from  PGP Encryption with BouncyCastle C# causes invalid key warning on signature verification | Webmaster Forum Archive

# June 1, 2010 7:09 PM

Halloween Costume Rentals » Pgp Zip Encrypted Files with C# – .Net Geek said:

Pingback from  Halloween Costume Rentals &raquo; Pgp Zip Encrypted Files with C# &#8211; .Net Geek

# September 21, 2010 7:13 PM

imran said:

Hello kim,

My client has a .net application that will create a .txt file and every month they send it to a bank, now my client wants to send the file in encrypted format using "PGP".  

My concerns are as follows:

1. Does my client needs a license FOR PGP (SDK)? OR  ( a free dll can be used )

2. PGP SDK does not support .NET, so is it possible for an average programmer to write a wrapper class(c#) for SDK ?

3. I am new to PGP, so please let me know how to achieve it in steps.

Thanks.

# October 3, 2010 3:56 PM

How to replace Linq Cast expression ? | DeveloperQuestion.com said:

Pingback from  How to replace Linq Cast expression ? | DeveloperQuestion.com

# October 26, 2010 1:21 PM

Donnie said:

The link provided shows some different examples of how GoAnywhere Director makes PGP, FTP, SFTP and more much easier.

# December 28, 2010 6:11 PM

Ian Lee said:

Thanks for the PGP classes!  However, I'm having a problem...  I can encrypt & sign my file fine but when the customer decrypts the file it is not exactly as it was when I encrypted.  Obviously, this is a huge problem.  Everything works fine if I use Kleopatra, so I believe the problem must exist in your code somewhere.  Email me at ian at houseoflees dot net if I can send you the files to inspect.

Thanks!

Ian

# January 28, 2011 7:07 AM

jaime baltodano said:

I got this error

Checksum mismatch at 0 of 20. and i cannot understand the cause. my code is in C#.net 2008

# March 22, 2011 7:12 PM

electronixbox said:

Bought a new TV!

# March 23, 2011 3:24 PM

psychoref said:

I want the space! How much does it cost?

# April 12, 2011 1:48 PM

yournewhouse said:

Bought a new TV!

# April 18, 2011 3:22 PM

praveen said:

hi jaime , can you please share your code in c#..my requirement is to encrypt/decrypt a text file using c# with PGP bouncy castle.

# May 21, 2011 11:54 AM

TheoSuccess said:

It is instructive. But I would not have been able to.

# June 18, 2011 1:30 PM

Swordconjuror said:

Very simple in words but in reality, many discrepancies, not so peachy!

# June 26, 2011 12:53 AM

immirmGem said:

A true belief in individual liberty and peace and a voting record to match it.

# February 5, 2012 5:36 AM

Sam said:

Thank you, so much!  This is exactly what we needed.

# April 6, 2012 6:03 PM

Encrypting email in C# using PGP public key [closed] | PHP Developer Resource said:

Pingback from  Encrypting email in C# using PGP public key [closed] | PHP Developer Resource

# May 24, 2012 2:07 AM

Gautham said:

What are public key file name and private key file name over here? How do we provide these parameters?

# July 3, 2012 3:36 PM

Aidas said:

Hi, who have tried MIKE's suggested EncryptDecrypt class? Encryption works fine, but Decrypt method throws an exception:

Org.BouncyCastle.Bcpg.OpenPgp.PgpException: Exception creating cipher ---> Org.BouncyCastle.Security.SecurityUtilityException: Cipher IDEA/CFB/NOPADDING not recognised.

  at Org.BouncyCastle.Security.CipherUtilities.GetCipher(String algorithm)

  at Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ExtractKeyData(Char[] passPhrase)

  --- End of inner exception stack trace ---

  at Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ExtractPrivateKey(Char[] passPhrase)

  at PGPEncryption.PGPEncryptDecrypt.FindSecretKey(PgpSecretKeyRingBundle pgpSec, Int64 keyId, Char[] pass) in D:\SVN\Tools\PGPEncryption\PGPEncryption\PGPEncryptDecrypt.cs:line 71

  at PGPEncryption.PGPEncryptDecrypt.DecryptFile(Stream inputStream, Stream keyIn, Char[] passwd, String pathToSaveFile) in D:\SVN\Tools\PGPEncryption\PGPEncryption\PGPEncryptDecrypt.cs:line 108

Cipher IDEA/CFB/NOPADDING not recognised.

  at Org.BouncyCastle.Security.CipherUtilities.GetCipher(String algorithm)

  at Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ExtractKeyData(Char[] passPhrase)

Here is the TEST function of mine. Am I missing something?

[Test]

       public void Should_Decrypt()

       {

           string privateKeyPath = @"D:\some_key.asc";

           string passPhrase = "some@pass";

           string EncryptedFileName = @"D:\original.pgp";

           string DecryptedFileName = @"D:\decrypted.xml";

           PGPEncryptDecrypt.Decrypt(EncryptedFileName, privateKeyPath, passPhrase, DecryptedFileName);

       }

# July 25, 2012 2:49 PM

affildeni said:

xpvjcvtr <a href=http://salesdrdreheadphonesoutletstore.info>beats by dre uk</a> onbjqyhnsq vzlgibmm <a href=http://salesguciibagsoutletstore.info>gucci uk</a> xyusithufx

# September 13, 2012 11:39 AM

donaldmcgrawsh said:

<a href="http://www.ventebotte.eu/#frV877kx">acheter">www.ventebotte.eu des uggs en france</a>  , uggs outlet jersey

<a href="www.bottesfemmepaschere.eu/#paV763cs">ugg">www.bottesfemmepaschere.eu soldes paris</a>  , acheter ugg espagne

<a href="www.bottesfemmepaschere.eu/#auV996ld">bottes">www.bottesfemmepaschere.eu ugg ugg pas cher ugg bottes acheter chaussures ugg australia</a>  , bottes ugg france

<a href="www.bottesfemmepaschere.eu/#geX705fr">ugg">www.bottesfemmepaschere.eu suisse geneve</a>  , how much are uggs at woodbury outlet

<a href="http://www.ventebotte.eu/#prX303hg">magasin">www.ventebotte.eu moncler paris prix</a>  , acheter polo moncler

<a href="http://www.ventebotte.eu/#coH258cs">ugg">www.ventebotte.eu outlet coupon</a>  , uggs sur paris .

http://www.ventebotte.eu

www.bottesfemmepaschere.eu.

# November 12, 2012 11:19 AM

NICKNAME said:

Stop hack the program!!!

# November 23, 2012 11:40 PM

NICKNAME said:

Stop hack the program!!!

# November 26, 2012 3:21 AM

qfvrwjvp@gmail.com said:

I know this comes at a busy time,Windows Server 2003 Key, with you most likely distracted by the European situation.

# December 7, 2012 7:12 AM

pwmcxr@gmail.com said:

they did in Cast Lead.Posted by: ToivoS | Nov 15, 2012 4:36:33 PM | 20@ Colm, re Iron Dome.

# December 13, 2012 1:39 PM

cerzevfvvjd@gmail.com said:

destroyed the owner of the elephant, so too, this prophecy will endure till the Day of Resurrection. Whenever any owners of the elephant arise, in order to destroy them,

# December 22, 2012 2:32 PM

Rudd said:

Fantastic beat ! I would like to apprentice whilst you amend your site, how can i subscribe for a weblog web

site? The account helped me a appropriate deal.

I were tiny bit acquainted of this your broadcast

provided shiny transparent concept

# March 19, 2013 5:10 AM

Jin7n said:

With besseren Zeiten darf es dann ebenso gern wieder G盲nseleber und Champagner geben, aber jetzt sind halt erst mal Bier sowie Bockwurst angesagt. Ganz and so einfach ist es jedoch nicht. Denn es will immer mehr thus scheinen, wie stecke der Luxus nicht nur in der Flaute, sondern throughout einer regelrechten Legitimationskrise.

Seit The year 2005 sind gerade douleur 3.384 St眉ck des D 6 verkauft worden, nicht inside Frankreich, insgesamt. Renault hatte seine barocke Fehlentwicklung Vel Satis schon 09 aufgegeben, Peugeot seinen 607 ein Jahr sp盲ter. Damit crown expire State, pass on auf der Welt f眉hrend ist durch Luxusartikeln von Herm猫s bis Lv, expire prachtvolle Bauwerke ihr Eigen nennt sowie durch Spitzenk眉che cease to live Gaumen verw枚hnt, with der automobilen Oberklasse nichts mehr zu bieten.

Expire Arbeitslosenquote fiel auf Six,Six von 8,Several Prozent -- vor allem weil immer mehr Menschen depart this life Jobsuche aufgeben. Depart this life Line liegt damit noch deutlich 眉ber dem Schnitt der vergangenen 50 Jahre von sechs Prozent. Nun k枚nnte sich r盲chen, dass sich Demokraten und Republikaner internet marketing erbittert gef眉hrten Haushaltsstreit instant messaging Kongress nicht einigen konnten.

# April 10, 2013 8:29 PM

Meo8 said:

For me personally, it had been on / off the actual motorbike the whole time. When investing in to your 4 way stop with Farlow Hole Trail (and that is wide open this specific signed being finished out of this course) the actual journey factors a person lower mountain for a [url=www.apsi.com.mx/insanityworkout.html]insanity workout[/url]

while, but requires back slope. Immediately after Farlow Space your trail is definitely many more rideable compared to you recently developed.

15 what to know to get now

# April 12, 2013 6:51 PM

Rolly4s said:

15 wonderful werewolf shift views remarks

Except if you've well-balanced your daily diet beautifully with the exercise technique, there may be some sort of [url=insanityworkoutdvds.tumblr.com]insanity workout[/url]

place in there for more vitamins and minerals along with vitamin antioxidants. A high-quality multi-vitamin can certainly add some of [url=insanityworkoutdvds.tumblr.com]insanity workout[/url]

these nutritionary spaces. To avoid trouble for the muscle flesh the result of 'free radicals' (reactive elements that will adversely destabilize additional substances), you might want to think about using supplements that includes Supplements A, Age, plus D; selenium along with glutamine can also help those people muscle groups temporarily injured through your strength training.

# April 17, 2013 4:28 AM

Myi6s said:

There is absolutely no these matter when failure simply abandoning. While E\dison bad On the lookout for,999 times in his tries to produce the electric powered light-bulb your dog didn't surrender. When quized with regards to his or her failures he stated, "I didn't been unsuccessful, I've got just discovered 9,999 strategies don't work!Inches.

Quantity In search of The actual [url=insanityworkoutdvds.tumblr.com]insanity workout DVD[/url]

Achy Breaky Poor Mistakey There are some movements which might be that should be left un-revived. Of which undoubtedly the way it is while using Painful Breaky, a new [url=insanityworkoutdvds.tumblr.com]insanity DVD[/url]

complicated crotch-thrusting set boogie empowered from the Billy Lewis Cyrus song. Very similar to bathroom hooch along with internet dating the sis, this is just one redneck craze you need to keep away from [url=insanityworkoutdvds.tumblr.com]insanity workout[/url]

-- except undertaking awful party movements outings a person's lead to.

# April 17, 2013 7:38 AM

Jin3d said:

Amongst [url=insanityworkoutdvds.tumblr.com]insanity DVD[/url]

the the reason why individuals do not think clearly about this issue that they seemingly don't even think regarding it in the least. If you think that Jimmy Grehan paid out 171m for your Two.Only two acre web site with [url=insanityworkoutdvds.tumblr.com]insanity workout[/url]

the previous veterinary clinic clinic throughout Dublin 4, you very well may commence to understand that all of the half-acre personal back yards all over Ballsbridge are creating the more costly carnations on earth. Those people made in Tiffany's are usually sugar-paste and salt-crystal by comparison.

12 notable exploitation motion pictures

# April 17, 2013 8:53 PM

Helton said:

With havin so much content and articles do you ever run into any issues of plagorism or

copyright violation? My website has a lot of

completely unique content I've either authored myself or outsourced but it seems a lot of it is popping it up all over the internet without my permission. Do you know any ways to help stop content from being stolen? I'd certainly appreciate it.

# April 21, 2013 5:00 AM

Quintero said:

Right now it appears like Wordpress is the top blogging platform

available right now. (from what I've read) Is that what you are using on your blog?

# April 21, 2013 11:34 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: