МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
ІКТА кафедра «Захист інформації»
Звіт
про виконання лабораторної роботи №3
з дисципліни
" Криптографія і стеганографія "
ПОТОКОВІ ШИФРИ
Мета роботи – Ознайомитися з основними алгоритмами побудови генераторів псевдовипадкових послідовностей та лінійними регістрами зсуву з зворотнім зв’язком.
Завдання
Підготувати програму на об'єктно-орієнтованій мові програмування, яка реалізовуватиме потоковий шифр на основі генератора з кількома РЗЛЗЗ, об’єднаних нелінійним способом, використовуючи дані відповідно до індивідуального завдання (див. табл.1).
Таблиця 1
Варіант
Генератор
РЗЛЗЗ
Поліном Р(х)
Текст
9
WAKE
2 Фібоначчі
ПІБ
Теоретичні відомості
WAKE
WAKE - скорочення від Word Auio Key Encryption (Автоматичне шифрування слів ключем) - це алгоритм, придуманий Дэвидом Уилером (David Wheeler)[1589]. Він видає потік 32-бітових слів, які за допомогою XOR можуть бути використані для отримання шифротекста з відкритого тексту або відкритого тексту з шифротекста. Це швидкий алгоритм.
WAKE працює в режимі CFB, для генерації наступного слова ключа використовується попереднє слово шифротекста. Алгоритм також використовує S -блок з 256 32-бітовых значень. Цей S -блок має одну особливу властивість: Старший байт усіх елементів є перестановкою усіх можливих байтів, а 3 молодші байти випадкові.
Спочатку по ключу згенеруємо елементи S-блоку, Si. Потім проініціалізуєм чотири регістри з використанням того ж або іншого ключа : a0,b0,c0 і d0. Для генерації 32-бітового слова потоку ключів Ki .
Слово шифротекста Сі є XOR слова відкритого тексту Рi з Ki. Потім відновимо чотири регістра:
Функція M є
Знак >>означає звичайне, не циклічне зрушення управо. Молодші 8 бітів х+у є входом S -блоку.
Рис.1 WAKE
Найціннішою якістю WAKE є його швидкість. Проте він чутливий до розкриття з вибраним відкритим текстом або вибраним шифротекстом. Цей алгоритм використовувався в попередній версії антивірусної програми д-ра Соломона.
Регістр Фібоначчі.
Загальний вид рекурентного співвідношення, що визначає генератор Фібоначчі, задається рівнянням
,
де - параметри генератора; елемент представляє собою двійковий k-вектор і дія виконується покомпонентно.
Рис.4. Регістр зсуву з лінійним зворотнім зв’язком Фібоначчі
Приклад: рядок (32, 7, 5, 3, 2, 1, 0) означає, що якщо взяти 32-бітовий регістр зсуву і генерувати нові біти XOR-складанням тридцять другого, сьомого, п'ятого, третього, другого і першого бітів, то результуюча послідовність матиме максимальний період - вона пройде через 232 - 1 значень до того, як почне повторюватися.
РЗЛЗЗ в програмній реалізації працюють досить повільно, і швидкість можна збільшити застосуванням для програмування мови Асемблер замість Сі. Ще одне можливе рішення - запускати 16 РЗЛЗЗ (або 32, залежно від розміру слова в комп'ютері) у паралельному режимі. Така схема використовує масив слів, так що кожна бітова комірка регістру представлена окремим РЗЛЗЗ. При умові, що всі вони мають один і той же поліном зворотного зв'язку, така схема працює досить швидко. У загальному випадку найкращий спосіб оновлювати стани регістрів зсуву - це множити поточний стан на відповідні двійкові матриці.
Текст програми:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
class Program
{
static void Main(string[] args)
{
Lab3 m = new Lab3();
m.Laba();
}
}
class Lab3
{
public uint[] Fibinachi(uint[] Vhidnui, uint[] PochatDani, uint[] ZvorotniZviaz)
{
uint alfa = 0;
uint index = 0;
while (index < Vhidnui.Length)
{
alfa = 0;
for (int i = 0; i < PochatDani.Length; i++)
if (ZvorotniZviaz[i] == 1)
alfa = SumModTwo(alfa, PochatDani[i]);
Vhidnui[index] = alfa;
for (int i = PochatDani.Length - 1; i > 0; i--)
PochatDani[i] = PochatDani[i - 1];
PochatDani[0] = Vhidnui[index];
index++;
}
return Vhidnui;
}
public uint SumModTwo(uint num1, uint num2)
{
if (num1 == num2)
return 0;
else
return 1;
}
public void Laba()
{
StreamReader streamReader = new StreamReader("1_word.txt");
string str = "";
while (!streamReader.EndOfStream)
{
str += streamReader.ReadLine();
}
streamReader.Close();
Console.WriteLine(str);
uint[] Pochatkovi = new uint[] { 0, 1, 1, 0, 1, 1, 0, 1, 1, 0 };
uint[] Key1 = new uint[30];
uint[] Key2 = new uint[1760];
uint[] ZZ1 = new uint[] { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
uint[] ZZ2 = new uint[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
Key1 = Fibinachi(Key1, Pochatkovi, ZZ1);
Key2 = Fibinachi(Key2, Key1, ZZ2);
ulong[] TenKey = new ulong[55];
TenKey = MakeTenArray(Key2, 55, 32);
ulong[] ATenKey = new ulong[300];
ulong[] BTenKey = new ulong[300];
for (int i = 0; i < TenKey.Length; i++)
{
ATenKey[i] = TenKey[i];
BTenKey[i] = TenKey[i];
}
char[] Word = str.ToCharArray();
Console.WriteLine(Word);
uint length_masseg = (UInt32)Word.Length;
ulong[] InWord = new ulong[Word.Length];
Console.WriteLine(Word.Length);
for (int i = 0; i < Word.Length; i++)
InWord[i] = (UInt64)((int)(Word[i]));
uint[] TwoFormWord = new uint[InWord.Length * 8];
TwoFormWord = MakeTwoArray(InWord, 0, length_masseg, 8);
Console.WriteLine(TwoFormWord.Length);
uint key_length = length_masseg * 8;
if (key_length % 32 != 0)
key_length = (UInt32)(key_length / 32) + 1;
else
key_length = (UInt32)(key_length / 32);
Console.WriteLine(key_length);
uint at = 55;
uint bt = 52;
ulong index = 0;
ulong[] BKey = new ulong[300];
while (true)
{
if (index != 0)
{
ATenKey[at] = ATenKey[at - 55] + ATenKey[at - 24];
ATenKey[at] = ATenKey[at] % (UInt64)(Math.Pow(2, 32));
BKey[at] = BTenKey[bt - 52] + BTenKey[bt - 19];
BKey[at] = BKey[bt] % (UInt64)(Math.Pow(2, 32));
Console.WriteLine(ATenKey[at]);
at++;
}
BTenKey[bt] = BTenKey[bt - 52] + BTenKey[bt - 19];
BTenKey[bt] = BTenKey[bt] % (UInt64)(Math.Pow(2, 32));
index = BTenKey[bt] % 2;
bt++;
if (at == 55 + key_length)
break;
}
uint[] ATwoArray = new uint[key_length * 32];
uint[] BTwoArray = new uint[key_length * 32];
ATwoArray = MakeTwoArray(ATenKey, 55, key_length, 32);
BTwoArray = MakeTwoArray(BKey, 55, key_length, 32);
uint[] Key = new uint[key_length * 32];
for (int i = 0; i < Key.Length; i++)
Key[i] = SumModTwo(ATwoArray[i], BTwoArray[i]);
Console.WriteLine(Key.Length);
string ShyfrWord = "";
uint[] ShyfrTwoForm = new uint[TwoFormWord.Length];
for (int i = 0; i < ShyfrTwoForm.Length; i++)
ShyfrTwoForm[i] = SumModTwo(TwoFormWord[i], Key[i]);
ulong[] ShyfrTenForm = new ulong[Word.Length];
ShyfrTenForm = MakeTenArray(ShyfrTwoForm, (UInt32)Word.Length, 8);
for (int i = 0; i < ShyfrTenForm.Length; i++)
ShyfrWord += (char)ShyfrTenForm[i];
Console.WriteLine(ShyfrWord);
StreamWriter sw = new StreamWriter("2_ShyfwrWord.txt");
sw.Write(ShyfrWord);
sw.Close();
string ReShyfrWord = "";
uint[] ReShyfrTwoForm = new uint[ShyfrTwoForm.Length];
for (int i = 0; i < ReShyfrTwoForm.Length; i++)
ReShyfrTwoForm[i] = SumModTwo(ShyfrTwoForm[i], Key[i]);
ulong[] ReShyfrTenForm = new ulong[Word.Length];
ReShyfrTenForm = MakeTenArray(ReShyfrTwoForm, (UInt32)Word.Length, 8);
for (int i = 0; i < ReShyfrTenForm.Length; i++)
ReShyfrWord += (char)ReShyfrTenForm[i];
Console.WriteLine(ReShyfrWord);
StreamWriter ws = new StreamWriter("3_ReShyfwrWord.txt");
ws.WriteLine(ReShyfrWord);
ws.Close();
}
public uint[] MakeTwoArray(ulong[] Array, uint Start, uint values, uint bits)
{
uint[] TwoArray = new uint[values * bits];
uint t = 0;
ulong k = 0;
for (uint i = Start; i < (Start + values); i++)
{
k = Array[i];
for (int j = 0; j < bits; j++)
{
if (k >= (UInt64)(Math.Pow(2, bits - 1 - j)))
{
TwoArray[t] = 1;
t++;
k = k - (UInt64)(Math.Pow(2, bits - 1 - j));
}
else
{
TwoArray[t] = 0;
t++;
}
}
}
return TwoArray;
}
public ulong[] MakeTenArray(uint[] Array, uint value, uint bits)
{
ulong[] TenArray = new ulong[value];
uint k = 0;
for (int i = 0; i < value; i++)
{
TenArray[i] = 0;
for (int j = 0; j < bits; j++)
TenArray[i] += (UInt64)(Array[j + k] * Math.Pow(2, bits - 1 - j));
k += bits;
}
return TenArray;
}
}
Результат роботи програми
Вміст файлу 1_word.txt: Zherebchuk Pavlo
Вміст файлу 2_ShyfwrWord.txt: vuMÉØòWMAõ@
Вміст файлу 1_ 3_ReShyfwrWord.txt: Zherebchuk Pavlo
Висновок
На цій лабораторній роботі я ознайомився з основними алгоритмами побудови генераторів псевдовипадкових послідовностей та лінійними регістрами зсуву з зворотнім зв’язком. Написав програму, яка поєднувала два лінійні регістри зсуву з зворотнім зв’язком Фібоначчі із різними поліномами, та автоматичним шифруванням слів ключем Wake.