/***********************************************************************************************************/


        #region ------ Constructor ------


        /// <summary>
        /// Constructs and initializes a blowfish instance with the supplied secret string.
        /// </summary>
        /// <param name="secretKey">The secret string to cipher with.</param>
        public BlowfishSymmetricCipher(string secretKey)
        {
            short i, j, k;
            uint  data, datal, datar;

            // Convert secret string into a byte array.
            byte[] key = SerializeDeserializeObject.StringToUTF8ByteArray(secretKey);

            P = _P.Clone() as uint[];
            S = _S.Clone() as uint[, ];

            j = 0;

            for (i = 0; i < N + 2; i++)
            {
                data = 0x00000000;
                for (k = 0; k < 4; k++)
                {
                    data = (data << 8) | key[j];
                    j++;
                    if (j >= key.Length)
                    {
                        j = 0;
                    }
                }
                P[i] = P[i] ^ data;
            }

            datal = 0x00000000;
            datar = 0x00000000;

            for (i = 0; i < N + 2; i += 2)
            {
                Encipher(ref datal, ref datar);
                P[i]     = datal;
                P[i + 1] = datar;
            }

            for (i = 0; i < 4; i++)
            {
                for (j = 0; j < 256; j += 2)
                {
                    Encipher(ref datal, ref datar);

                    S[i, j]     = datal;
                    S[i, j + 1] = datar;
                }
            }
        }
        /***********************************************************************************************************/


        #region ------ Public Methods ------


        /// <summary>
        /// Encrypts a byte array in place.
        /// </summary>
        /// <param name="data">The array to encrypt.</param>
        /// <param name="length">The amount to encrypt.</param>
        public void Encipher(ref byte[] data, int length)
        {
            uint xl;
            uint xr;

            while ((length % 8) != 0)
            {
                byte[] addonByte = SerializeDeserializeObject.StringToUTF8ByteArray(" ");

                length += addonByte.Length;

                Array.Resize <byte>(ref data, length);

                for (int i = 0; i < addonByte.Length; i++)
                {
                    data[length - 1 + i] = addonByte[i];
                }
            }

            for (int i = 0; i < length; i += 8)
            {
                // Encode the data in 8 byte blocks.
                xl = (uint)((data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | data[i + 3]);
                xr = (uint)((data[i + 4] << 24) | (data[i + 5] << 16) | (data[i + 6] << 8) | data[i + 7]);

                Encipher(ref xl, ref xr);

                // Now Replace the data.
                data[i]     = (byte)(xl >> 24);
                data[i + 1] = (byte)(xl >> 16);
                data[i + 2] = (byte)(xl >> 8);
                data[i + 3] = (byte)(xl);
                data[i + 4] = (byte)(xr >> 24);
                data[i + 5] = (byte)(xr >> 16);
                data[i + 6] = (byte)(xr >> 8);
                data[i + 7] = (byte)(xr);
            }
        }