Автор работы: Пользователь скрыл имя, 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 Приложение
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(
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 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 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,
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,
0x082efa98,0xec4e6c89,
0xc0ac29b7,0xc97c50dd,
};
}
private uint[] SetupS0()
{
return new uint[] {
0xd1310ba6,0x98dfb5ac,
0xba7c9045,0xf12c7f99,
0x636920d8,0x71574e69,
0x718bcd58,0x82154aee,
0xc5d1b023,0x286085f0,
0x6c9e0e8b,0xb01e8a3e,
0xe65525f3,0xaa55ab94,
0xb4cc5c34,0x1141e8ce,
0x2ba9c55d,0x741831f6,
0x7a325381,0x28958677,
0x61d809cc,0xfb21a991,
0xdc262302,0xeb651b88,
0x2e0b4482,0xa4842004,
0x670c9c61,0xabd388f0,
0x6eef0b6c,0x137a3be4,
0x66ca593e,0x82430e88,
0xe06f75d8,0x85c12073,
0x1bfedf72,0x429b023d,
0x075372c9,0x80991b7b,
0x976ce0bd,0x04c006ba,
0x68fb6faf,0x3e6c53b5,
0xcc814544,0xaf5ebd09,
0xc0cba857,0x45c8740f,
0xd6a100c6,0x402c7279,
0x3c7516df,0xfd616b15,
0x53317b48,0x3e00df82,
0xd542a8f6,0x287effc3,
0xe1ffa35d,0xb8f011a0,
0x9a53e479,0xb6f84565,
0x62fb1341,0xcee4c6e8,
0x95dbda4d,0xae909198,
0x8e3c5b2f,0x8e7594b7,
0x4fad5ea0,0x688fc31c,
0xea752dfe,0x8b021fa1,
0xb4a84fe0,0xfd13e0b7,
0x93cc7314,0x211a1477,
0xebcdaf0c,0x7b3e89a0,
0x226800bb,0x57b8e0af,
0x78c14389,0xd95a537f,
0x11c81968,0x4e734a41,
0xd60f573f,0xbc9bc6e4,
0xf296ec6b,0x2a0dd915,
0x53b02d5d,0xa99f8fa1,
};
}
private uint[] SetupS1()
{
return new uint[] {
0x4b7a70e9,0xb5b32944,