/// <summary>
        ///     Encrypts the specified plain data.
        /// </summary>
        /// <param name="plainData">The plain data.</param>
        /// <param name="remotePublicKeyXML">The remote public key XML.</param>
        /// <returns>
        ///     The encrypted data.
        /// </returns>
        /// <externalUnit/>
        /// <revision revisor="dev01" date="1/26/2009" version="1.0.5.7">
        ///     Member Created
        /// </revision>
        public byte[] Encrypt(
            byte[] plainData,
            string remotePublicKeyXML)
        {
            // Ecnrypted data placeholder
            byte[] encryptedData = null;

            //Calculate the hash and append it to the data
            byte[] dataPlusHash =
                SequoiaCryptoProvider.AppendArrays(
                    this.CalculateHash(plainData),
                    plainData);

            // Symmetrically Encrypt data and hash with random key and IV
            byte[] encryptedDataPlusHash =
                this.SymmetricallyEncryptContent(dataPlusHash);

            // Create an Encrypted transport Key
            var transKey = new TransportKey(
                this.SymmetricCrypto.Key,
                this.SymmetricCrypto.IV,
                this);

            // Add transport Key to ecnrypted data
            encryptedData =
                SequoiaCryptoProvider.AppendArrays(
                    transKey.GenerateTransportKey(remotePublicKeyXML),
                    encryptedDataPlusHash);

            return(encryptedData);
        }
        /// <summary>
        ///     Decrypts the specified complete encrypted data.
        /// </summary>
        /// <param name="completeEncryptedData">The complete encrypted data.</param>
        /// <param name="localPrivateKeyXML">The local private key XML.</param>
        /// <returns>
        ///     The decrypted data.
        /// </returns>
        /// <externalUnit/>
        /// <revision revisor="dev01" date="1/26/2009 1:23:15 PM" version="1.0.5.7">
        ///     Member Created
        /// </revision>
        public byte[] Decrypt(
            byte[] completeEncryptedData,
            string localPrivateKeyXML)
        {
            byte[] decryptedData = null;
            byte[] hash          = null;
            try
            {
                // Generate the Transport Key
                TransportKey transportKey = new TransportKey(
                    SequoiaCryptoProvider.Subarray(
                        completeEncryptedData,
                        0,
                        this.TransportKeySize),
                    this);

                // Extract encrypted data (total - transport key)
                byte[] encryptedData =
                    SequoiaCryptoProvider.Subarray(
                        completeEncryptedData,
                        this.TransportKeySize);

                // Decrypt the data and Hash with decrypted symmetric key and IV
                byte[] decryptedDataPlusHash =
                    this.SymmetricallyDecryptContent(
                        encryptedData,
                        transportKey.GetSymmetricKeyFromTransportKey(
                            localPrivateKeyXML),
                        transportKey.GetSymmetricIVFromTransportKey(
                            localPrivateKeyXML));

                hash =
                    SequoiaCryptoProvider.Subarray(
                        decryptedDataPlusHash,
                        0,
                        this.Hasher.HashSize / BitsInByte);

                // Extarct the final data
                decryptedData =
                    SequoiaCryptoProvider.Subarray(
                        decryptedDataPlusHash,
                        this.Hasher.HashSize / BitsInByte);
            }
            catch (Exception exc)
            {
                throw new CryptographicException("Wrong data to decrypt.", exc);
            }

            if (SequoiaCryptoProvider.CompareHashes(
                    hash,
                    this.CalculateHash(decryptedData)) != true)
            {
                throw new CryptographicException("Hash Mismatch.");
            }

            return(decryptedData);
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="TransportKey"/> class.
        /// </summary>
        /// <param name="encryptedKey">The encrypted key.</param>
        /// <param name="crypto">The crypto provider.</param>
        /// <externalUnit/>
        /// <revision revisor="dev01" date="1/30/2009" version="1.0.5.11">
        ///     Member Created
        /// </revision>
        public TransportKey(
            byte[] encryptedKey, SequoiaCryptoProvider crypto)
        {
            this.encryptedData = encryptedKey;

            this.encrypted        = true;
            this.asymmetricCrypto = crypto.AsymmetricCrypto;
            this.shortKeys        = crypto.ShortKeys;
        }
 /// <summary>
 ///     Creates a sub version of the array
 /// </summary>
 /// <returns>The piece of the array</returns>
 /// <param name="mainArray">First Array to merge</param>
 /// <param name="index">Index to start the subarray </param>
 /// <revision revisor="dev01" date="1/28/2009" version="1.0.5.9">
 ///     Method created.
 /// </revision>
 public static byte[] Subarray(
     byte[] mainArray,
     int index)
 {
     return(SequoiaCryptoProvider.Subarray(
                mainArray,
                index,
                mainArray.Length - index));
 }
 /// <summary>
 ///     Initializes a new instance of the <see cref="TransportKey"/> class.
 /// </summary>
 /// <param name="crypto">The crypto.</param>
 /// <externalUnit/>
 /// <revision revisor="dev01" date="2/5/2009" version="1.0.6.1">
 ///     Member Created
 /// </revision>
 public TransportKey(
     SequoiaCryptoProvider crypto)
 {
     this.key = crypto.SymmetricCrypto.Key;
     this.asymmetricCrypto     = crypto.AsymmetricCrypto;
     this.initializationVector = crypto.SymmetricCrypto.IV;
     this.encrypted            = false;
     this.shortKeys            = crypto.ShortKeys;
 }
 /// <summary>
 ///     Initializes a new instance of the <see cref="TransportKey"/> class.
 /// </summary>
 /// <param name="encryptionKey">The encryption key.</param>
 /// <param name="initializationVector">
 ///     The initialization vector.
 /// </param>
 /// <param name="crypto">the crypto provider.</param>
 /// <externalUnit/>
 /// <revision revisor="dev01" date="1/30/2009" version="1.0.5.11">
 ///     Member Created
 /// </revision>
 public TransportKey(
     byte[] encryptionKey,
     byte[] initializationVector,
     SequoiaCryptoProvider crypto)
 {
     this.asymmetricCrypto = crypto.AsymmetricCrypto;
     this.key = encryptionKey;
     this.initializationVector = initializationVector;
     this.encrypted            = false;
     this.shortKeys            = crypto.ShortKeys;
 }
        /// <summary>
        ///     Generates the transport key.
        /// </summary>
        /// <param name="remotePublicKeyXML">The remote public key XML.</param>
        /// <returns>
        ///     The transport key.
        /// </returns>
        /// <externalUnit cref="AsymmetricAlgorithm"/>
        /// <revision revisor="dev01" date="1/30/2009" version="1.0.5.11">
        ///     Member Created
        /// </revision>
        public byte[] GenerateTransportKey(string remotePublicKeyXML)
        {
            if (encrypted == false)
            {
                this.encryptedData =
                    SequoiaCryptoProvider.AppendArrays(
                        this.AsymmetricallyEncryptContent(
                            this.key, remotePublicKeyXML),
                        this.AsymmetricallyEncryptContent(
                            this.initializationVector, remotePublicKeyXML));
                encrypted = true;
            }

            return(this.encryptedData);
        }
 /// <summary>
 ///     Decrypts the transport key.
 /// </summary>
 /// <param name="privateKeyXML">The private key XML.</param>
 /// <externalUnit/>
 /// <revision revisor="dev01" date="1/30/2009" version="1.0.5.11">
 ///     Member Created
 /// </revision>
 public void DecryptTransportKey(string privateKeyXML)
 {
     if (this.encrypted == true)
     {
         this.key = this.AsymmetricallyDecryptContent(
             SequoiaCryptoProvider.Subarray(
                 this.encryptedData,
                 0,
                 this.AsymmetricCrypto.KeySize / 8),
             privateKeyXML);
         this.initializationVector =
             this.AsymmetricallyDecryptContent(
                 SequoiaCryptoProvider.Subarray(
                     this.encryptedData,
                     this.AsymmetricCrypto.KeySize / 8),
                 privateKeyXML);
         this.encrypted = false;
     }
 }
        /// <summary>
        ///     Symmetrically decrypt the content.
        /// </summary>
        /// <param name="encryptedData">The encrypted data.</param>
        /// <param name="symmetricKey">The symmetric key.</param>
        /// <param name="symmetricIV">The symmetric IV.</param>
        /// <returns>
        ///     The decrypted content.
        /// </returns>
        /// <externalUnit/>
        /// <revision revisor="dev01" date="1/26/2009 1:23:15 PM" version="1.0.5.7">
        ///     Member Created
        /// </revision>
        private byte[] SymmetricallyDecryptContent(
            byte[] encryptedData,
            byte[] symmetricKey,
            byte[] symmetricIV)
        {
            // Memory Stream to read the encrypted data
            byte[] decryptedBytes  = null;
            int    decryptRealSize = 0;

            // Cryptostream to decrypt teh memory stream
            using (var memoryStream = new MemoryStream(encryptedData))
            {
                using (var cryptoStream =
                           new CryptoStream(
                               memoryStream,
                               this.SymmetricCrypto.CreateDecryptor(
                                   symmetricKey,
                                   symmetricIV),
                               CryptoStreamMode.Read))
                {
                    // Placeholder for decrypted data (size it with the
                    // encrypted data length (maybe larger but then
                    // will crop it)
                    decryptedBytes = new byte[encryptedData.Length];

                    // Start decrypting.
                    decryptRealSize =
                        cryptoStream.Read(
                            decryptedBytes, 0, encryptedData.Length);
                }
            }

            // REVIEW: null check on decrypted bytes before proceeding.

            // Need subarray, because placeholder array maybe larger than the
            // actual data
            return(SequoiaCryptoProvider.Subarray(
                       decryptedBytes,
                       0,
                       decryptRealSize));
        }