Міністерство освіти і науки України
Національний університет Львівська політехніка
Курсовий поект
з дисципліни: “Методи та засоби
криптологічних перетворень”
Львів — 2010
Зміст
Завдання стр. 3
Опис використаних методів шифрування
Лінійний шифр k–ого порядку стр. 3
Алгоритм шифрування RSA стр. 4
Розроблення алгоритму зашифрування лінійним шифром k–ого порядку стр. 7
Розроблення алгоритму зашифрування алгоритмом RSA стр. 11
Результати роботи програм зашифрування стр. 16
Висновки стр. 17
Список використаної літератури стр. 18
Номер залікової книжки: 0609114
Завдання №1
Симетричне шифрування
Вибрати ключі та розробити програму для зашифрування файлу даних лінійним афінним шифром 3-ого порядку (2 + 1 mod 4 = 3). Об’єм афлавіту NA повинен становити 64 (25+1 = 26 = 64).
Завдання №2
Асиметричне шифрування
Зашифрувати слово ШУМ відкритого тексту за алгоритмом RSA. Дані параметри згідно з варіантом: p = 5, q = 13; n = p * q = 65; phi(n) = (p - 1) * (q - 1) = 48; е = 23, було обране навмання з діапазону 1 < e < phi(n), таке що НСД(е, phi(n)) = 1.
Представлення слова ШУМ у цифровій формі Ш=28 У=23 М=16, тобто {28,23,16}.
Опис використаних методів шифрування
1. Шифри простої заміни.
n-символьний алфавіт утотожнюємо з кільцем Zn. А саме, кожна буква замінюється своїм номером у алфавіті, прийому нумерація починається з нуля.
Наприклад, латинська абетка утотожнюється із Z26, а українська із Z33. Літера а української абетки трактується як 0, літера б як 1, в як 2 і т.д. Тепер до букв відкритого тексту ми можемо вільно застосовувати операції додавання та множення за відповідним модулем.
Шифр зсуву.
Ключ: s таке, що 0 < s < п.
Шифрування. У повідомленні кожна буква х заміщується буквою Е(х) = (х + s) mod n.
Дешифрування. У криптотексті кожна буква х' заміщується буквою D(x') = (х' + s') mod п, де
s' = п - s. Величину зворотнього зсуву s' будемо називати дешифруючим ключем.
Лінійний шифр.
Ключ: а таке, що 0 < а < п і НСД (а, п) = 1.
Шифрування. У повідомленні кожна буква х заміщується буквою Е{х) = (ах) mod n.
Дешифрування. У криптотексті кожна буква х' заміщується буквою D(x') = (a'x') mod п, де
а' = a-1 mod n — дешифруючий ключ.
Узагальненням і шифру зсуву, і лінійного шифру є Афінний шифр.
Ключ: a, s такі, що 0 < s < п, 0 < а <п і НСД (а, п) = 1.
Шифрування. У повідомленні кожна буква х заміщується буквою Е(х) = (ах + s) mod n.
Дешифрування. У криптотексті кожна буква х' заміщується буквою D(x') = (a'x'+ s’) mod n, де пара а’ = a-1 mod n, s’ = (-a’s) mod n є дешифруючим ключем.
Як і кожен шифр простої заміни, афінний шифр піддається частотному аналізові.
2. Афінні шифри вищих порядків.
Подумаємо, як можна розширити монограмні шифри попереднього пункту так, щоб вони оперували з k-грамами для довільного k > 1. Спочатку введемо операцію додавання в Znk. Сумою векторів X = (x1,. . .,хk) і s = (s1,… ,sk) з Znk є вектор X + S = ((x1 + s1) mod n,…, (хk + sk) mod n). Zkn з операцією додавання є групою. Вектор -S = (n — s1,…, n — sk) є оберненим до вектора
S = (s1,…,sk).
Шифр зсуву k-го порядку.
Ключ: S є Zkn.
Шифрування. Повідомлення розбивається на k-грами. Кожна k-грама X заміщується k-грамою Е(Х) = X + S.
Дешифрування. Кожна k-грама X' криптотексту заміщується k-грамою D(X') = X' + 5’, де
S' = -S є дешифруючим ключем.
Лінійний шифр k-го порядку.
Ключ: А Є GLk(Zn).
Шифрування. Повідомлення розбивається на k-грами. Кожна k-грама X заміщується k-грамою Е(Х)= АХ.
Дешифрування. Кожна k-грама Х’ криптотексту заміщується k-грама D(X') = A'X', де
А’ = А-1 — дешифруючий ключ.
Афінний шифр k-го порядку.
Ключ: А Є GLk{Zn} і S Є Znk.
Шифрування. Повідомлення розбивається на k-грами. Кожна k-грама X заміщується k-грамою Е(Х) = АХ + S.
Дешифрування. Кожна k-грама X' криптотексту заміщується k-грамою D{X’} = А’X’ + S’, де А’ = А-1 і S’ = -A’S — дешифруючий ключ.
3. Алгоритм RSA
Безпека алгоритму RSA побудована на принципі складності факторизації. Алгоритм використовує два ключі — відкритий (public) і секретний (private), разом відкритий і відповідний йому секретний ключі утворюють пари ключів (keypair). Відкритий ключ не потрібно зберігати в таємниці, він використовується для шифрування даних. Якщо повідомлення було зашифровано відкритим ключем, то розшифрувати його можна тільки відповідним секретним ключем.
Генерація ключів
Для того, щоб згенерувати пари ключів виконуються наступні дії:
вибираються два великих простих числа и
обчислюється їх добуток
обчислюється Функція Ейлера
вибирається ціле таке, що та взаємно просте з
за допомогою розширеного алгоритма Евкліда знаходиться число таке, що
Число називається модулем, а числа і — відкритою й секретною експонентами, відповідно. Пари чисел є відкритою частиною ключа, а — секретною. Числа і після генерації пари ключів можуть бути знищені, але в жодному разі не повинні бути розкриті.
Шифрування й розшифрування
Для того, щоб зашифрувати повідомлення обчислюється
.
Число використовується в якості шифртексту. Для розшифрування потрібно обчислити
.
Неважко переконатися, що при розшифруванні ми відновимо вихідне повідомлення:
З умови
виходить, що
для деякого цілого , отже
Згідно теореми Ейлера:
,
тому
Цифровий підпис
RSA може використовуватися не тільки для шифрування, але й для цифрового підпису.
Підпис повідомлення обчислюється з використанням секретного ключа за формулою:
Для перевірки правильності підпису потрібно переконатися, що виконується рівність
Генерація простих чисел
Для знаходження двох великих простих чисел і , при генерації ключа, звичайно використовуються ймовірносні тести чисел на простоту, які дозволяють швидко виявити й відкинути складні числа.
Для генерації і необхідно використовувати криптографічно надійний генератор випадкових чисел. У порушника не має бути можливості одержати будь-яку інформацію про значення цих чисел.
і не повинні бути занадто близькими одне до одного, інакше можна буде знайти їх використовуючи метод факторизації Ферма. Крім того, необхідно вибирати «сильні» прості числа, щоб не можна було скористатися алгоритмом Поларда.
Доповнення повідомлень
При практичному використанні необхідно деяким чином доповнювати повідомлення. Відсутність доповнень може призвести до деяких проблем:
значення і дадуть при зашифруванні шифртексти 0 і 1 при будь-яких значеннях і .
при малому значенні відкритого показника (, наприклад) можлива ситуація, коли виявиться, що . Тоді , і зловмисник легко зможе відновити вихідне повідомлення обчисливши корінь ступеня з .
оскільки RSA є детермінованим алгоритмом, тобто не використовує випадкових значень у процесі роботи, то зловмисник може використати атаку з обраним відкритим текстом.
Для розв'язання цих проблем повідомлення доповнюються перед кожним зашифруванням деяким випадковим значенням. Доповнення виконується таким чином, щоб гарантувати, що , і . Крім того, оскільки повідомлення доповнюється випадковими даними, то зашифровуючи той самий відкритий текст ми щораз будемо одержувати інше значення шифртексту, що робить атаку з обраним відкритим текстом неможливою.
Вибір значення відкритого показника
RSA працює значно повільніше симетричних алгоритмів. Для підвищення швидкості шифрування відкритий показник вибирається невеликим, звичайно 3, 17 або 65537. Ці числа у двійковому вигляді містять тільки по двох одиниці, що зменшує число необхідних операцій множення при піднесенні до степеня. Наприклад, для піднесення числа до степеня 17 потрібно виконати тільки 5 операцій множення:
Вибір малого значення відкритого показника може призвести до розкриття повідомлення, якщо воно відправляється відразу декільком одержувачам, але ця проблема вирішується за рахунок доповнення повідомлень.
Вибір значення секретного показника
Значення секретного показника повинне бути досить великим. У 1990 році Міхаель Вінер (Michael J. Wiener) показав, що якщо і , то є ефективний спосіб обчислити по і . Однак, якщо значення вибирається невеликим, те виявляється досить великим і проблеми не виникає.
Довжина ключа
Число n повинне мати розмір не менше 512 біт. У даний момент (2007 рік) система шифрування на основі RSA вважається надійною, починаючи з величини N в 1024 біта.
Розроблення алгоритму зашифрування
лінійним афінним шифром k-ого порядку
В даному випадку, згідно із завданням курсового проекту, необхідно розробити алгоритм зашифрування 3-ого порядку. Це означає, що нашим ключем буде матриця 3х3, НСД усіх елементів якої має дорінювати 1. Для зашифрування нашого повідомлення, нам доведеться розбити його на k-грами по символів, після чого помножити ці k-грами на матрицю-ключ.
Список функцій, змінних та констант
використаних в програмі
alpha[] – масив в якому знаходяться букви латинського алфавіту;
source[] – масив в який заноситься повідомлення;
result[] – масив в який буде записуватись текст із файлу з зашифрованим текстом, для подальшого виводу на екран;
digital_text[] – масив, в який записується числова інтерпретація відкритого тексту;
A[][] – масиви в які записуються ключі в числовій інтерпретації;
X[][] – масив в який записується відкритий текст в числовій інтерпретації;
digital_eresult[] – масив в який зберігаються результати зашифрування у вигляді індексів букв у відповідних алфавітах;
i, j, temp – змінні що використовуються в лічильниках циклів;
tlen – довжина повідомлення;
alen – довжина алфавіту;
dlen – кількість стовпців в матриці, в яку записаний текст повідомлення;
C – константа, що визначає довжину повідомлення;
N – константа, що визначає об’єм алфавіту, всі обчислення здійснюються за модулем цього числа;
K – константа, що визначає порядок шифру, також вказує розмір матриці-ключа (КхК);
strlen() – визначення довжини рядка, який може бути заданий напряму або в масиві;
printf() – функція, що виводить текст і/або змінні на екран;
scanf() – функція, що зчитує введену користувачем інформацію з клавіатури;
fprintf() – функція, що записує текст і/або змінні в файл;
fscanf() – функція, що зчитує інформацію з файлу;
fclose() – функція, що закриває файл та зберігає його вміст;
fopen() – функція, що відкриває файл для читання і/або запису;
*ptext , *etext – покажчики на файл з відкритим та зашифрованим текстом, відповідно;
Блок схема програми зашифрування лінійним афінним шифром
Текст програми
#include<stdio.h>
#include<string.h>
#define C 255 /* максимальна довжина повідомлення */
#define N 64 /* об’єм алфавіту */
#define K 3 /* порядок шифру, розмірність матриці ключа */
void main(void) {
char alpha[N] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4',
'5', '6', '7', '8', '9', '0' };
char source[C], /* масив для запису відкритого тексту з файлу */
result[C]; /* масив для виводу зашифрованого тексту з файлу */
int digital_text[C], /* масив з порядковими номерами букв відкритого тексту */
A[K][K] = {{17, 17, 11},
{10, 23, 17},
{ 9, 23, 7}}; /* масив-ключ */
int i, j, tlen, alen, dlen, temp = 0;
FILE *ptext; /* файл в якому записаний відкритий текст */
FILE *etext; /* файл в який записується зашифрований текст */
/* Введення відкритого тексту з файлу та формування масивів для подальших */
/* розрахунків */
ptext = fopen("source.txt", "r");
fscanf(ptext, "%s", source);
printf("\n\n\tSource text:\t %s", source);
alen = strlen(alpha) - 1; /* обрахунок буквенної довжени алфавіту */
tlen = strlen(source) - 1; /* обрахунок довжини відкритого тексту */
for (i=0; i<=tlen; i++) /* формування масиву в який будуть записані */
{ for (j=0; j<=alen; j++) /* індекси букв відкритого тексту */
{ if (source[i] == alpha[j]) digital_text[i] = j;
}
}
if (( (tlen/K) % K ) == 0) dlen = round(tlen/K);
else dlen = round(tlen/K) + 1;
int X[dlen][K], /* оголошення масиву Nх5, в який буде */
/* записуватись результат шифрування */
digital_eresult[dlen][K]; /* масив в який буде заноситись */
/* результат шифрування */
Продовження стр. 1Продовження стр. 1
for (i=0; i<=(dlen-1); i++) /* заповнюємо матрицю Nх5 індексами букв */
{ for (j=0; j<=(K-1); j++)
{ X[i][j] = digital_text[temp];
temp++;
}
}
temp = 0;
/* Зашифрування */
for (i=0; i<=(dlen-1); i++)
{ for (j=0; j<=(K-1); j++)
{ digital_eresult[i][j] = ( A[0][j] * X[i][0] )
+ ( A[1][j] * X[i][1] )
+ ( A[2][j] * X[i][2] );
if (digital_eresult[i][j] >= N) /* модуль від попередньої операції */
digital_eresult[i][j] = digital_eresult[i][j] % N;
}
}
/* Вивід результатів зашифрування на екран, та запис цих результатів в файл */
etext = fopen("encrypted.txt", "w");
for (i=0; i<=(dlen-1); i++) /* посимвольне записування зашифрованого */
{ for (j=0; j<=(K-1); j++) /* тексту в файл */
{ if (temp < (tlen+1))
{ fprintf(etext, "%c", alpha[digital_eresult[i][j]]);
temp++;
}
}
}
temp = 0;
etext = fopen("encrypted.txt", "r");
fscanf(etext, "%s", result);
printf("\n\n\tEncrypted text:\t %s", result);
/* Збереження данних програми, та її завершення */
printf("\n\n\n\n\tPress any key to continue...");
fclose(ptext);
fclose(etext);
getch();
}
Розроблення алгоритму зашифрування
aлгоритмом RSA
В даному випадку, згідно із варіантом завдання, необхідно зашифрувати слово ШУМ алгоритмом RSA. Нам дано p = 5 і q = 13, е можна обрати на вибір. Всі інші елементи ми будемо дізнаватись за допомогою реалізації програмних засобів для їх знаходження.
Список функцій, змінних та констант
використаних в програмі
X – константа, що визначає довжину слова яке може бути опрацьоване програмою;
phi – змінна, яка відповідає змінній Phi(n) у алгоритмі RSA;
M[] – масив в який заносеться повідомлення;
n – змінна, яка відповідає змінній n в алгоритмі RSA;
e – змінна, яка відповідає змінній e в алгоритмі RSA;
d – змінна, яка відповідає змінній d в алгоритмі RSA;
C[] – масив, в якому зберігається зашифрований текст;
FLAG – змінна, що використовується в обрахунках;
i, j – змінні, що використовуються в лічильниках циклів;
q – змінна, яка відповідає змінній q в алгоритмі RSA;
p – змінна, яка відповідає змінній p в алгоритмі RSA;
s – змінна, що використовується в обрахунках.
Блок-схема програми зашифрування алгоритмом RSA
Текст програми
#include<stdio.h>
#define X 3 /* Вказуємо довжину слова */
int phi, M[X], n, e, d, C[X], FLAG;
int check() /* Функція що перевіряє */
/* чи НСД(е,phi(n))=1 */
{ int i;
for(i=3; e%i==0 && phi%i==0; i+2)
{ FLAG = 1;
return;
}
FLAG = 0;
}
void encrypt() /* Функція, що проводить зашифування */
/* слова побуквенно, після чого */
/* виводить результат */
{ int i, j;
for(j=0; j<X; j++) C[j] = 1;
for(j=0; j<X; j++)
{ for(i=0; i<e; i++) C[j] = (C[j] * M[j]) % n;
}
printf("\n\tEncrypted keyword:\t");
for(j=0; j<X; j++)
{ C[j] = C[j] % n;
printf(" %d", C[j]);
}
}
void decrypt() /* Функція, що проводить розшифрування */
/* слова побуквенно, після чого */
/* виводить результат */
{ int i, j;
for(j=0; j<X; j++) M[j] = 1;
for(j=0; j<X; j++)
{ for(i=0; i<d; i++) M[j] = (M[j] * C[j]) % n;
}
printf("\n\tDecrypted keyword:\t");
for(j=0; j<X; j++)
{ M[j] = M[j] % n;
printf(" %d", M[j]);
}
}
Продовження стр. 1Продовження стр. 1
void main(void)
{ int p, q, s;
printf("\n\tEnter Two Relatively Prime Numbers:\t");
scanf("%d %d", &p, &q);
n = p * q;
phi = (p - 1) * (q - 1);
printf("\n\t phi(n):\t%d", phi);
do
{ printf("\n\n\tEnter E:\t");
scanf("%d", &e);
check();
}
while(FLAG == 1);
d = 1;
do /* Знаходження оберненого */
/* елементу d до е */
{ s = (d * e) % phi;
d++;
}
while(s!=1);
d--;
printf("\n\tPublic Key:\t{%d,%d}", e, n);
printf("\n\tPrivate Key:\t{%d,%d}", d, n);
printf("\n\n\n\tEnter plain text:\t ");
scanf("%d %d %d", &M[0], &M[1], &M[2]);
encrypt();
/*
printf("\n\n\n\tEnter encrypted text:\t ");
scanf("%d %d %d", &C[0], &C[1], &C[2]);
decrypt();
*/
printf("\n\n\tPress any key to continue...");
getch();
}
Результат виконання програми
зашифрування лінійним афінним шифром
5-ого порядку
Результат виконання програми
зашифрування алгоритмом RSA
Висновок
Список використаної літератури
О.В.Вербіцький. Вступ до криптології. Львів., "ВНТЛ", 1998.
И.М.Виноградов. Основы теории чисел. М., "Наука", 9-е издание 1981.
В.Жельников. Криптография от папируса до компьютера. М., "АВР", 1996.
К.Шеннон. Теория связи в секретных системах. В Работы по теории информации и кибернетике, стр. 333-402. М, Изд. Иностр. Лит., 1963.
М.Вельшенбах. Криптография на С и С++ в действии. М., Триумф, 2004.
Б.Шнайер. Прикладная криптография, 2-е издание: протоколы, алгоритмы, исходные тексты на языке Си. М., Триумф, 2002.