Алгоритм шифрования Blowfish

Автор работы: Пользователь скрыл имя, 21 Мая 2013 в 19:32, курсовая работа

Описание работы

Скорость шифрования алгоритма во многом зависит от используемой техники и системы команд. На различных архитектурах один алгоритм может значительно опережать по скорости его конкурентов, а на другом ситуация может сравняться или даже измениться прямо в противоположную сторону. Более того, программная реализация значительно зависит от используемого компилятора. Использование ассемблерного кода может повысить скорость шифрования. На скорость шифрования влияет время выполнения операций mov, add, xor, причём время выполнения операций увеличивается при обращении к оперативной памяти (для процессоров серии Pentium примерно в 5 раз). Blowfish показывает более высокие результаты при использовании кэша для хранения всех подключей. В этом случае он опережает алгоритмы DES, IDEA.

Содержание работы

Содержание
• 1 Введение
• 2 Описание алгоритма
o 2.1 Параметры
o 2.2 Функция F(x)
o 2.3 Алгоритм шифрования 64-битного блока с известным массивом P и F(x)
o 2.4 Алгоритм Blowfish
o 2.5 Выбор начального значения P-массива и таблицы замен
• 3 Криптостойкость
• 4 Пример работы алгоритма
• 5 Применения
• 6 Заключение
• 7 Список литературы
• 8 Приложение

Файлы: 1 файл

ЗАПИСКА_BLOWFISH.docx

— 106.73 Кб (Скачать файл)

            HexToByte(ct))).Replace("\0","");

        }

 

        /// <summary>

        /// Encrypts a byte array in ECB mode

        /// </summary>

        /// <param name="pt">Plaintext data</param>

        /// <returns>Ciphertext bytes</returns>

        public byte[] Encrypt_ECB(byte[] pt)

        {

            return Crypt_ECB(pt, false);

        }

 

        /// <summary>

        /// Decrypts a byte array (ECB)

        /// </summary>

        /// <param name="ct">Ciphertext byte array</param>

        /// <returns>Plaintext</returns>

        public byte[] Decrypt_ECB(byte[] ct)

        {

            return Crypt_ECB(ct, true);

        }

 

        /// <summary>

        /// Initialization vector for CBC mode.

        /// </summary>

        public byte[] IV

        {

            get { return InitVector; }

            set

            {

                if (value.Length == 8)

                {

                    InitVector = value;

                    IVSet = true;

                }

                else

                {

                    throw new Exception("Invalid IV size.");

                }

            }

        }

 

        public bool NonStandard

        {

            get { return nonStandardMethod; }

            set { nonStandardMethod = value; }

        }

 

        /// <summary>

        /// Creates and sets a random initialization vector.

        /// </summary>

        /// <returns>The random IV</returns>

public byte[] SetRandomIV()

        {

            InitVector = new byte[8];

            randomSource.GetBytes(InitVector);

            IVSet = true;

            return InitVector;

        }

 

        #region Cryptography

            

        /// <summary>

        /// Sets up the S-blocks and the key

        /// </summary>

        /// <param name="cipherKey">Block cipher key (1-448

bits)</param>

        private void SetupKey(byte[] cipherKey)

        {

            bf_P = SetupP();

            //set up the S blocks

            bf_s0 = SetupS0();

            bf_s1 = SetupS1();

            bf_s2 = SetupS2();

            bf_s3 = SetupS3();

 

            key = new byte[cipherKey.Length]; // 448 bits

            if (cipherKey.Length > 56)

            {

                throw new Exception("Key too long. 56 bytes required.");

            }

 

            Buffer.BlockCopy(cipherKey, 0, key, 0, cipherKey.Length);

            int j = 0;

            for (int i = 0; i < 18; i++)

            {

                uint d = (uint)(((key[j % cipherKey.Length] * 256 +

key[(j + 1) % cipherKey.Length]) * 256 + key[(j + 2) %

cipherKey.Length]) * 256 + key[(j + 3) % cipherKey.Length]);

                bf_P[i] ^= d;

                j = (j + 4) % cipherKey.Length;

            }

 

            xl_par = 0;

            xr_par = 0;

            for (int i = 0; i < 18; i += 2)

            {

                encipher();

                bf_P[i] = xl_par;

                bf_P[i + 1] = xr_par;

            }

 

            for (int i = 0; i < 256; i += 2)

            {

                encipher();

                bf_s0[i] = xl_par;

                bf_s0[i + 1] = xr_par;

            }

            for (int i = 0; i < 256; i += 2)

            {

                encipher();

                bf_s1[i] = xl_par;

                bf_s1[i + 1] = xr_par;

            }

            for (int i = 0; i < 256; i += 2)

            {

                encipher();

                bf_s2[i] = xl_par;

                bf_s2[i + 1] = xr_par;

            }

            for (int i = 0; i < 256; i += 2)

            {

                encipher();

                bf_s3[i] = xl_par;

                bf_s3[i + 1] = xr_par;

            }

        }

 

        /// <summary>

        /// Encrypts or decrypts data in ECB mode

        /// </summary>

        /// <param name="text">plain/ciphertext</param>

        /// <param name="decrypt">true to decrypt, false to encrypt</param>

        /// <returns>(En/De)crypted data</returns>

        private byte[] Crypt_ECB(byte[] text, bool decrypt)

        {

            int paddedLen = (text.Length % 8 == 0 ? text.Length : text.Length

+ 8 - (text.Length % 8));

            byte[] plainText = new byte[paddedLen];

            Buffer.BlockCopy(text, 0, plainText, 0, text.Length);

            byte[] block = new byte[8];

            for (int i = 0; i < plainText.Length; i += 8)

            {

                Buffer.BlockCopy(plainText,i, block, 0, 8);

                if (decrypt)

                {

                    BlockDecrypt(ref block);

                }

                else

                {

                    BlockEncrypt(ref block);

                }

                Buffer.BlockCopy(block, 0, plainText, i, 8);

            }

            return plainText;

        }

 

        /// <summary>

        /// Encrypts or decrypts data in CBC mode

        /// </summary>

        /// <param name="text">plain/ciphertext</param>

        /// <param name="decrypt">true to decrypt, false to encrypt</param>

        /// <returns>(En/De)crypted data</returns>

        private byte[] Crypt_CBC(byte[] text, bool decrypt)

        {

            if (!IVSet)

            {

                throw new Exception("IV not set.");

            }

            int paddedLen = (text.Length % 8 == 0 ? text.Length : text.Length

+ 8 - (text.Length % 8));

            byte[] plainText = new byte[paddedLen];

            Buffer.BlockCopy(text, 0, plainText, 0, text.Length);

            byte[] block = new byte[8];

            byte[] preblock = new byte[8];

            byte[] iv = new byte[8];

            Buffer.BlockCopy(InitVector,0,iv,0,8);

            if (!decrypt)

            {

                for (int i = 0; i < plainText.Length; i += 8)

                {

                    Buffer.BlockCopy(plainText, i, block, 0, 8);

                    XorBlock(ref block, iv);

                    BlockEncrypt(ref block);

                    Buffer.BlockCopy(block, 0, iv, 0, 8);

                    Buffer.BlockCopy(block, 0, plainText, i, 8);

                }

            }

            else

            {

                for (int i = 0; i < plainText.Length; i += 8)

                {

                    Buffer.BlockCopy(plainText, i, block, 0, 8);

 

                    Buffer.BlockCopy(block, 0, preblock, 0, 8);

                    BlockDecrypt(ref block);

                    XorBlock(ref block, iv);

                    Buffer.BlockCopy(preblock, 0, iv, 0, 8);

 

                    Buffer.BlockCopy(block, 0, plainText, i, 8);

                }

            }

            return plainText;

        }

 

        /// <summary>

        /// XoR encrypts two 8 bit blocks

        /// </summary>

        /// <param name="block">8 bit block 1</param>

        /// <param name="iv">8 bit block 2</param>

        private void XorBlock(ref byte[] block, byte[] iv)

        {

            for (int i = 0; i < block.Length; i++)

            {

                block[i] ^= iv[i];

            }

        }

 

        /// <summary>

        /// Encrypts a 64 bit block

        /// </summary>

        /// <param name="block">The 64 bit block to encrypt</param>

        private void BlockEncrypt(ref byte[] block)

        {

            SetBlock(block);

            encipher();

            GetBlock(ref block);

        }

 

        /// <summary>

        /// Decrypts a 64 bit block

        /// </summary>

        /// <param name="block">The 64 bit block to decrypt</param>

        private void BlockDecrypt(ref byte[] block)

        {

            SetBlock(block);

            decipher();

            GetBlock(ref block);

        }

 

        /// <summary>

        /// Splits the block into the two uint values

        /// </summary>

        /// <param name="block">the 64 bit block to setup</param>

        private void SetBlock(byte[] block)

        {

            byte[] block1 = new byte[4];

            byte[] block2 = new byte[4];

            Buffer.BlockCopy(block, 0, block1, 0, 4);

            Buffer.BlockCopy(block, 4, block2, 0, 4);

            //split the block

            if (nonStandardMethod)

            {

                xr_par = BitConverter.ToUInt32(block1, 0);

                xl_par = BitConverter.ToUInt32(block2, 0);

            }

            else

            {

                //ToUInt32 requires the bytes in reverse order

                Array.Reverse(block1);

                Array.Reverse(block2);

                xl_par = BitConverter.ToUInt32(block1, 0);

                xr_par = BitConverter.ToUInt32(block2, 0);

            }

        }

 

        /// <summary>

        /// Converts the two uint values into a 64 bit block

        /// </summary>

        /// <param name="block">64 bit buffer to receive the block</param>

        private void GetBlock(ref byte[] block)

        {

            byte[] block1 = new byte[4];

            byte[] block2 = new byte[4];

            if (nonStandardMethod)

            {

                block1 = BitConverter.GetBytes(xr_par);

                block2 = BitConverter.GetBytes(xl_par);

            }

            else

            {

                block1 = BitConverter.GetBytes(xl_par);

                block2 = BitConverter.GetBytes(xr_par);

 

                //GetBytes returns the bytes in reverse order

                Array.Reverse(block1);

                Array.Reverse(block2);

            }

            //join the block

            Buffer.BlockCopy(block1, 0, block, 0, 4);

            Buffer.BlockCopy(block2, 0, block, 4, 4);

        }

 

        /// <summary>

        /// Runs the blowfish algorithm (standard 16 rounds)

        /// </summary>

        private void encipher()

        {

            xl_par ^= bf_P[0];

            for (uint i = 0; i < 16; i+= 2)

            {

                xr_par = round(xr_par, xl_par, i + 1);

                xl_par = round(xl_par, xr_par, i + 2);

            }

            xr_par = xr_par ^ bf_P[17];

 

            //swap the blocks

            uint swap = xl_par;

            xl_par = xr_par;

            xr_par = swap;

        }

 

        /// <summary>

        /// Runs the blowfish algorithm in reverse (standard 16 rounds)

        /// </summary>

        private void decipher()

        {

            xl_par ^= bf_P[17];

            for (uint i = 16; i > 0; i -= 2)

            {

                xr_par = round(xr_par, xl_par, i );

                xl_par = round(xl_par, xr_par, i-1);

            }

            xr_par = xr_par ^ bf_P[0];

 

            //swap the blocks

            uint swap = xl_par;

            xl_par = xr_par;

            xr_par = swap;

        }

 

        /// <summary>

        /// one round of the blowfish algorithm

        /// </summary>

        /// <param name="a">See spec</param>

        /// <param name="b">See spec</param>

        /// <param name="n">See spec</param>

        /// <returns></returns>

        private uint round(uint a, uint b, uint n)

        {

            uint x1 = (bf_s0[wordByte0( B) ] + bf_s1[wordByte1( B) ]) ^

bf_s2[wordByte2( B) ];

            uint x2 = x1 + bf_s3[this.wordByte3( B) ];

            uint x3 = x2 ^ bf_P[n];

            return x3 ^ a;

        }

 

        #endregion

 

        #region SBLOCKS

        //SBLOCKS ARE THE HEX DIGITS OF PI.

        //The amount of hex digits can be increased if you want to experiment with

more rounds and longer key lengths

        private uint[] SetupP()

        {

            return new uint[] {

                0x243f6a88,0x85a308d3,0x13198a2e,0x03707344,0xa4093822,0x299f31d0,

                    0x082efa98,0xec4e6c89,0x452821e6,0x38d01377,0xbe5466cf,0x34e90c6c,

                    0xc0ac29b7,0xc97c50dd,0x3f84d5b5,0xb5470917,0x9216d5d9,0x8979fb1b

            };

        }

 

        private uint[] SetupS0()

        {

            return new uint[] {

                    0xd1310ba6,0x98dfb5ac,0x2ffd72db,0xd01adfb7,0xb8e1afed,0x6a267e96,

                    0xba7c9045,0xf12c7f99,0x24a19947,0xb3916cf7,0x0801f2e2,0x858efc16,

                    0x636920d8,0x71574e69,0xa458fea3,0xf4933d7e,0x0d95748f,0x728eb658,

                    0x718bcd58,0x82154aee,0x7b54a41d,0xc25a59b5,0x9c30d539,0x2af26013,

                    0xc5d1b023,0x286085f0,0xca417918,0xb8db38ef,0x8e79dcb0,0x603a180e,

                    0x6c9e0e8b,0xb01e8a3e,0xd71577c1,0xbd314b27,0x78af2fda,0x55605c60,

                    0xe65525f3,0xaa55ab94,0x57489862,0x63e81440,0x55ca396a,0x2aab10b6,

                    0xb4cc5c34,0x1141e8ce,0xa15486af,0x7c72e993,0xb3ee1411,0x636fbc2a,

                    0x2ba9c55d,0x741831f6,0xce5c3e16,0x9b87931e,0xafd6ba33,0x6c24cf5c,

                    0x7a325381,0x28958677,0x3b8f4898,0x6b4bb9af,0xc4bfe81b,0x66282193,

                    0x61d809cc,0xfb21a991,0x487cac60,0x5dec8032,0xef845d5d,0xe98575b1,

                    0xdc262302,0xeb651b88,0x23893e81,0xd396acc5,0x0f6d6ff3,0x83f44239,

                    0x2e0b4482,0xa4842004,0x69c8f04a,0x9e1f9b5e,0x21c66842,0xf6e96c9a,

                    0x670c9c61,0xabd388f0,0x6a51a0d2,0xd8542f68,0x960fa728,0xab5133a3,

                    0x6eef0b6c,0x137a3be4,0xba3bf050,0x7efb2a98,0xa1f1651d,0x39af0176,

                    0x66ca593e,0x82430e88,0x8cee8619,0x456f9fb4,0x7d84a5c3,0x3b8b5ebe,

                    0xe06f75d8,0x85c12073,0x401a449f,0x56c16aa6,0x4ed3aa62,0x363f7706,

                    0x1bfedf72,0x429b023d,0x37d0d724,0xd00a1248,0xdb0fead3,0x49f1c09b,

                    0x075372c9,0x80991b7b,0x25d479d8,0xf6e8def7,0xe3fe501a,0xb6794c3b,

                    0x976ce0bd,0x04c006ba,0xc1a94fb6,0x409f60c4,0x5e5c9ec2,0x196a2463,

                    0x68fb6faf,0x3e6c53b5,0x1339b2eb,0x3b52ec6f,0x6dfc511f,0x9b30952c,

                    0xcc814544,0xaf5ebd09,0xbee3d004,0xde334afd,0x660f2807,0x192e4bb3,

                    0xc0cba857,0x45c8740f,0xd20b5f39,0xb9d3fbdb,0x5579c0bd,0x1a60320a,

                    0xd6a100c6,0x402c7279,0x679f25fe,0xfb1fa3cc,0x8ea5e9f8,0xdb3222f8,

                    0x3c7516df,0xfd616b15,0x2f501ec8,0xad0552ab,0x323db5fa,0xfd238760,

                    0x53317b48,0x3e00df82,0x9e5c57bb,0xca6f8ca0,0x1a87562e,0xdf1769db,

                    0xd542a8f6,0x287effc3,0xac6732c6,0x8c4f5573,0x695b27b0,0xbbca58c8,

                    0xe1ffa35d,0xb8f011a0,0x10fa3d98,0xfd2183b8,0x4afcb56c,0x2dd1d35b,

                    0x9a53e479,0xb6f84565,0xd28e49bc,0x4bfb9790,0xe1ddf2da,0xa4cb7e33,

                    0x62fb1341,0xcee4c6e8,0xef20cada,0x36774c01,0xd07e9efe,0x2bf11fb4,

                    0x95dbda4d,0xae909198,0xeaad8e71,0x6b93d5a0,0xd08ed1d0,0xafc725e0,

                    0x8e3c5b2f,0x8e7594b7,0x8ff6e2fb,0xf2122b64,0x8888b812,0x900df01c,

                    0x4fad5ea0,0x688fc31c,0xd1cff191,0xb3a8c1ad,0x2f2f2218,0xbe0e1777,

                    0xea752dfe,0x8b021fa1,0xe5a0cc0f,0xb56f74e8,0x18acf3d6,0xce89e299,

                    0xb4a84fe0,0xfd13e0b7,0x7cc43b81,0xd2ada8d9,0x165fa266,0x80957705,

                    0x93cc7314,0x211a1477,0xe6ad2065,0x77b5fa86,0xc75442f5,0xfb9d35cf,

                    0xebcdaf0c,0x7b3e89a0,0xd6411bd3,0xae1e7e49,0x00250e2d,0x2071b35e,

                    0x226800bb,0x57b8e0af,0x2464369b,0xf009b91e,0x5563911d,0x59dfa6aa,

                    0x78c14389,0xd95a537f,0x207d5ba2,0x02e5b9c5,0x83260376,0x6295cfa9,

                    0x11c81968,0x4e734a41,0xb3472dca,0x7b14a94a,0x1b510052,0x9a532915,

                    0xd60f573f,0xbc9bc6e4,0x2b60a476,0x81e67400,0x08ba6fb5,0x571be91f,

                    0xf296ec6b,0x2a0dd915,0xb6636521,0xe7b9f9b6,0xff34052e,0xc5855664,

                    0x53b02d5d,0xa99f8fa1,0x08ba4799,0x6e85076a

            };

        }

 

        private uint[] SetupS1()

        {

            return new uint[] {

                0x4b7a70e9,0xb5b32944,0xdb75092e,0xc4192623,0xad6ea6b0,0x49a7df7d,

Информация о работе Алгоритм шифрования Blowfish