МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ „ЛЬВІВСЬКА ПОЛІТЕХНІКА”
Лабораторна робота №3
Проектування засобів захисту інформації в комп’ютерних мережах
«Алгоритм симетричного блокового шифрування CAST128»
Львів – 2015
Мета роботи: реалізувати програму симетричного блокового шифрування повідомлення за алгоритмом CAST128.
Теоретичні відомості
У криптографії, CAST-128 (або CAST5) блоковий алгоритм симетричного шифрування на основі мережі Фейстеля, що використовується в цілому ряді продуктів криптографічного захисту, зокрема деяких версіях PGP й GPG і крім того схвалений для використання Канадським урядом. Алгоритм був створений в 1996 році Карлайлом Адамсом (Carlisle Adams) і Стаффордом Таваресом (Stafford Tavares), використовуючи метод побудови шифрів CAST, що використовується також й іншим їхнім алгоритмом CAST-256 (алгоритм-кандидат AES)
Мережа Фе́йстеля (конструкція Фейстеля) — один з методів побудови блокових шифрів. Мережа представляє із себе певну ітеровану структуру, що називається коміркою Фейстеля. При переході від однієї комірки до іншої міняється ключ, причому вибір ключа залежить від конкретного алгоритму. Операції шифрування та дешифрування на кожному етапі дуже прості, і при певній доробці збігаються, вимагаючи тільки зворотного порядку використовуваних ключів. Шифрування за допомогою даної конструкції легко реалізуються як на програмному рівні, так і на апаратному, що забезпечує широкі можливості застосування. Більшість сучасних блокових шифрів використовують мережу Фейстеля як основу. Альтернативою мережі Фейстеля є підстановочно-перестановочна мережа.
Конструкція блокового шифру на основі мереж Фейстеля
Шифрування
Розшифрування
Шифрування
Розглянемо випадок, коли ми хочемо зашифрувати деяку інформацію, представлену у двійковому вигляді в комп'ютерній пам'яті (наприклад, файл) або електроніці, як послідовність нулів й одиниць.
Вся інформація розбивається на блоки фіксованої довжини. У випадку, якщо довжина вхідного блоку менше, ніж розмір, що шифрується заданим алгоритмом, то блок подовжується яким-небудь способом. Як правило довжина блоку є ступенем двійки, наприклад: 64 біта, 128 біт. Далі будемо розглядати операції, що відбуваються тільки з одним блоком, тому що з іншими в процесі шифрування виконуються ті ж самі операції.
Обраний блок ділиться на два рівних подблока — «лівий» (L0) і «правий» (R0).
«Лівий подблок» L0 видозмінюється функцією f(L0,K0) залежно від раундового ключа K0, після чого він додається по модулі 2 з «правим підблоком» R0.
Результат додавання присвоюється новому лівому підблоку L1, що буде половиною вхідних даних для наступного раунду, а «лівий подблок» L0 присвоюється без змін новому правому підблоку1 (див. схему), що буде іншою половиною.
Після чого операція повторюється N-1 раз, при цьому при переході від одного етапу до іншого міняються раундові ключі (K0 на K1 і т.д.) за яким-небудь математичним правилом, де N — кількість раундів у заданому алгоритмі. Розшифрування
інформації відбувається так само, як і шифрування, з тією лише відмінністю, що ключі йдуть у зворотному порядку, тобто не від першого до N-ному, а від N-го до першого.
Код програми:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lab5
{
class cast128
{
private int _NUM_OF_ROUNDS = 12;
UInt32 f( UInt32 part, short k )
{
UInt32 tmp;
for (int i = 0; i < k; i++ )
{
tmp = part<<31;
part >>= 1;
part |= tmp;
}
return part;
}
private byte[] EncryptBlock64( byte[] DataBlock64, UInt64 key )
{
UInt32 L,R,L1=0,R1=0;
byte[] res = new byte[8];
if (DataBlock64.Count() != 8)
{
System.Windows.Forms.MessageBox.Show("ERROR");
res.Initialize();
return res;
}
short k;
L = (UInt32)DataBlock64[0];
L <<= 8;
L |= (UInt32)DataBlock64[1];
L <<= 8;
L |= (UInt32)DataBlock64[2];
L <<= 8;
L |= (UInt32)DataBlock64[3];
R = (UInt32)DataBlock64[4];
R <<= 8;
R |= (UInt32)DataBlock64[5];
R <<= 8;
R |= (UInt32)DataBlock64[6];
R <<= 8;
R |= (UInt32)DataBlock64[7];
for (int i = 0; i < _NUM_OF_ROUNDS; i++ )
{
k = (short)(key >> (5 * i));
k &= 0x1f;
L1 = R ^ f(L, k);
R1 = L;
//----
L = L1;
R = R1;
}
res[0] = (byte)(L1 >> 24);
res[1] = (byte)(L1 >> 16);
res[2] = (byte)(L1 >> 8);
res[3] = (byte)L1;
res[4] = (byte)(R1 >> 24);
res[5] = (byte)(R1 >> 16);
res[6] = (byte)(R1 >> 8);
res[7] = (byte)R1;
return res;
}
private byte[] DecryptBlock64(byte[] DataBlock64, UInt64 key)
{
UInt32 L, R,L1=0,R1=0;
byte[] res = new byte[8];
if (DataBlock64.Count() != 8)
{
System.Windows.Forms.MessageBox.Show("ERROR");
res.Initialize();
return res;
}
short k;
L = (UInt32)DataBlock64[0];
L <<= 8;
L |= (UInt32)DataBlock64[1];
L <<= 8;
L |= (UInt32)DataBlock64[2];
L <<= 8;
L |= (UInt32)DataBlock64[3];
R = (UInt32)DataBlock64[4];
R <<= 8;
R |= (UInt32)DataBlock64[5];
R <<= 8;
R |= (UInt32)DataBlock64[6];
R <<= 8;
R |= (UInt32)DataBlock64[7];
for (int i = _NUM_OF_ROUNDS - 1; i >= 0; i--)
{
k = (short)(key >> (5 * i));
k &= 0x1f;
L1 = R;
R1 = L ^ f(R, k);
//----
L = L1;
R = R1;
}
res[0] = (byte)(L1 >> 24);
res[1] = (byte)(L1 >> 16);
res[2] = (byte)(L1 >> 8);
res[3] = (byte)L1;
res[4] = (byte)(R1 >> 24);
res[5] = (byte)(R1 >> 16);
res[6] = (byte)(R1 >> 8);
res[7] = (byte)R1;
return res;
}
public void EncryptText( string text, UInt64 key, string file_name)
{
System.IO.FileStream fs = new System.IO.FileStream(file_name, System.IO.FileMode.Create);
int i = 0;
byte[] block = new byte[8];
while( text.Length % 4 != 0 )
{
text = text.Insert(text.Length, " ");
}
while( i < text.Length )
{
block[0] = (byte)text[i];
block[1] = (byte)(text[i]>>8);
block[2] = (byte)text[i+1];
block[3] = (byte)(text[i+1]>>8);
block[4] = (byte)text[i+2];
block[5] = (byte)(text[i+2]>>8);
block[6] = (byte)text[i+3];
block[7] = (byte)(text[i+3]>>8);
fs.Write(EncryptBlock64(block,key),0,8);
i += 4;
}
fs.Close();
}
public void DecryptText(UInt64 key, string encrypted_file, string new_file)
{
System.IO.FileStream fs1 = new System.IO.FileStream(encrypted_file, System.IO.FileMode.Open);
System.IO.FileStream fs2 = new System.IO.FileStream(new_file, System.IO.FileMode.Create);
int i = 0;
byte[] block = new byte[8];
while ( i < fs1.Length)
{
fs1.Read(block, 0, 8);
fs2.Write(DecryptBlock64(block, key), 0, 8);
i += 8;
}
fs1.Close();
fs2.Close();
}
}
}
Результати виконання роботи:
Висновки: ознайомився з алгоритмом шифрування CAST-128. Написав програму, яка реалізує даний алгоритм.