МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
ЛАБОРАТОРНИЙ ПРАКТИКУМ № 2
З КУРСУ “КРИПТОГРАФІЧНІ ПЕРЕТВОРЕННЯ ”
для студентів спеціальності 6.1601 “Інформаційна безпека”
Затверджено
на засiданнi кафедри
“Автоматика та телемеханiка”
Протокол № 14 від 21.04.2005 р.
Львів – 2005
Методичні вказівки для виконання лабораторних робіт з курсу «Криптографічні перетворення». Дослідження симетричних алгоритмів шифрування. Інструкція до лабораторної роботи №4 з курсу “Криптографічні перетворення” для студентів спеціальності 6.1601 “Інформаційна безпека”/ укл.: В.О. Хорошко, М.Є. Шелест, В.Б. Дудикевич,
І.Б. Ломницький, А.Я. Горпенюк – Львів: НУЛП, 2005.- 18 с.
Укладачі: В.О. Хорошко, д.т.н., професор,
М.Є. Шелест, д.т.н., професор,
В.Б. Дудикевич, д.т.н., професор, І.Б. Ломницький, асистент,
А.Я. Горпенюк, к.т.н., доцент.
Відповідальний за випуск: В.Б. Дудикевич, д.т.н., професор.
Рецензент: Л.Т. Пархуць, к.т.н., доцент.
ЛАБОРАТОРНИЙ ПРАКТИКУМ № 2
З КУРСУ “КРИПТОГРАФІЧНІ ПЕРЕТВОРЕННЯ ”
для студентів спеціальності 6.1601
“Інформаційна безпека”
ДОСЛІДЖЕННЯ СИМЕТРИЧНИХ АЛГОРИТМІВ ШИФРУВАННЯ
Вступ.
Існує два основних типи алгоритмів, заснованих на ключах: симетричні й алгоритми з відкритим ключем.
Симетричні алгоритми, які іноді називають класичними алгоритмами, являють собою алгоритми, у яких ключ шифрування може бути розрахований по ключу дешифрування і навпаки. У більшості симетричних алгоритмів ключі шифрування і дешифрування ті ж самі. Ці алгоритми, також називають алгоритмами із таємним ключем чи алгоритмами з одним ключем, які вимагають, щоб відправник і одержувач погодили використовуваний ключ перед початком безпечної передачі повідомлень. Безпека симетричного алгоритму визначається ключем; розкриття ключа означає, що хто завгодно зможе шифрувати й дешифрувати повідомлення. Поки передані повідомлення повинні бути таємними, ключ повинен зберігатися в секреті.
Шифрування й дешифрування з використанням симетричного алгоритму записується як:
EК(M)=C (1)
DК(C)=M (2)
При цьому виконується наступна рівність (див. рис. 1):
DК(ЕК(M))=M (3)
Симетричні алгоритми поділяються на дві категорії. Одні алгоритми обробляють відкритий текст побітно (іноді побайтно), вони називаються потоковими алгоритмами або алгоритмами потокового шифрування. Інші працюю з групами бітів відкритого тексту. Групи бітів називаються блоками, а алгоритми - блоковими алгоритмами шифрування чи блоковими шифрами. Для алгоритмів, використовуваних у комп'ютерних системах, типовий розмір блоку складає 64 біта - досить велике значення, щоб перешкодити криптоаналізу, і досить невелике й зручне для роботи.
Ключ Ключ
Відтворений
Відкритий відкритий
текст Шифротекст текст
Рис. 1. Шифрування й дешифрування з одним ключем.
Далі ми докладніше познайомимся з блоковим симетричним алгоритмом шифрування DES.
Лабораторна робота № 4.
Тема. Дослідження алгоритму шифрування даних DES.
Мета роботи. Вивчити структуру та принципи функціонування алгоритму шифрування DES, на практиці здійснити формування ключа, зашифрувати відкритий текст і розшифрувати зашифроване повідомлення даним алгоритмом. Дослідити сильні і слабкі сторони алгоритму DES.
Короткі теоретичні відомості.
Cтандарт шифрування даних (DES) був впроваджений в листопаді 1976 року. В стандарт входить опис «блокового шифру типу Файстеля» з різними режимами його роботи, як складової частини декількох процедур криптографічного перетворення даних. Зазвичай під абревіатурою DES розуміється саме «блоковий шифр» (див. нижче), який у стандарті відповідає процедурі шифрування в режимі ЕСВ (Electronic Сodebook Моdе). Назва викликана тим, що будь-який “блоковий шифр” є шифром простої заміни й у цьому відношенні подібний кодовій таблиці.
Пояснимо суть блокового шифру. Входом у блоковий шифр і результатом його роботи є блок довжиною п - послідовність, яка складається з п бітів. Число п постійне. При необхідності зашифровування повідомлення довжиною більшою п воно розбивається на блоки, кожен з яких шифрується окремо. Різні режими роботи пов'язані з додатковими ускладненнями блокового шифру під час переходів від блоку до блоку. В стандарті DES довжина блоку п = 64.
У режимі ЕСВ зашифровування блоку відкритого тексту В проходить за 16 однотипних ітерацій, які називаються циклами.
Блок розглядається як конкатенація (зчеплення) двох підблоків: В = (L,R). Довжини підблоків L і R рівні. В кожному циклі застосовується свій ключ (Kі), зазвичай він певним чином генерується з основного ключа (K). Ключі, які використовуються в циклах називаються підключами.
Основним елементом шифру є несекретна циклова функція, яка має вигляд . Входом у цикл є вихід з попереднього циклу. Якщо згаданий вхід має вигляд (L,R), то вихід має вигляд де - порозрядне додавання за модулем 2. Більш точніше, для виходу циклу з номером і, це означає наступне:
, , (i=1…16).
У режимі ЕСВ алгоритм DES зашифровує 64-бітний блок за 16 циклів. Біти вхідного блоку перед першим циклом переставляються за підстановкою ІР (таб.1). Після виходу з останнього циклу L і R переставляються місцями, після чого з'єднуються в блок. Біти отриманого блоку переставляються за ІР-1. Результат приймається як блок шифротексту.
Схема перетворення приведена на рис. 2, а на рис. 3 наведено процедуру формування підключів.
Рис.2. Блок-схема роботи алгоритму DES в режимі ЕСВ.
Рис.3. Блок-схема формування підключів.
В кожному циклі ключ Kі має розмір 48 біт і є підвибіркою з ключа K довжиною в 56 біт. Сам ключ K розміщується у вигляді восьмибайтового слова. Восьмі розряди байтів є контрольними і в ключ не входять. Перед зашифровуванням, відповідно до процедури вибору PC1 (таб. 2), з K вибираються 56 біт, якими заповнюються два регістри (С,D). Далі, під час входження в чергову ітерацію з номером і, регістри зсуваються циклічно вліво. Величина зсуву залежить від номера циклу, але є фіксованою і відома. Після зсуву обидва підблоки з’єднуються в послідовності С, D. Потім, відповідно до функції вибору РС2 (таб. 3), з них вибираються 48 біт підключа Kі. Зашифровування і розшифровування відрізняються послідовністю зсувів та кількістю біт зсуву ключа для кожного етапу зашифровування (таб. 4).
Таблиця 1. Перетворення ІР.
58
50
42
34
26
18
10
2
60
52
44
36
28
20
12
4
62
54
46
38
ЗО
22
14
6
64
56
48
40
32
24
16
8
57
49
41
33
25
17
9
1
59
51
43
35
27
19
11
3
61
53
45
37
29
21
13
5
63
55
47
39
31
23
15
7
Таблиця 2. Перетворення РС1.
Заповнення С
Заповнення D
57 49 41 33 25 17 9
1 58 50 42 34 26 18
10 2 59 51 43 35 27
19 11 3 60 52 44 36
63 55 47 39 31 23 15
7 62 54 46 38 З0 22
14 6 61 53 45 37 29
21 13 5 28 20 12 4
Таблиця 3. Перетворення РС2.
14
17
11
24
1
5
3
28
15
6
21
10
23
19
12
4
26
8
16
7
27
20
13
2
41
52
31
37
47
55
30
40
51
45
33
48
44
49
39
56
34
53
46
42
50
36
29
32
Таблиця 4. Кількість розрядів ключа, які зсуваються на кожному етапі зашифровування.
Вибір бітів за таблицями 1-3 з відповідних блоків здійснює в такий спосіб. Таблиця розглядається як послідовність її рядків, записаних один за одним, починаючи з першого рядка. Біти блоку даних відповідної довжини нумеруються зліва направо, починаючи з одиниці. Кожен елемент S – таблиці розглядається як номер біта bs в блоці даних. Перетворення полягає в заміні всіх елементів s на біти bs.
Циклічна функція робить такі дії:
а) розширення блоку Ri-1 до 48 біт за рахунок повторення його бітів при допомозі функції розширення ЕР;
б) порозрядне додавання результату з ключем Kі;
в) перетворення отриманої суми за допомогою заміни (використовуючи так звані S - блоки), у результаті якого виходить блок довжини 32 біта;
г) перестановку результату заміни за постійною і відомою підстановкою Р, що дає значення функції .
Механізм дії S-блоків. Перетворення, за допомогою якого 48 – розрядний блок перетвориться в 32-розрядний, полягає у вибірці восьми тетрад з 8 таблиць (S-блоків) розміром 4 на 16. З кожного S-блоку вибирається одна тетрада. Для цього 48-розрядний блок ділиться послідовно на 8 комбінацій по 6 біт у кожній. Перша комбінація (зліва) є входом у перший S-блок, друга - у другий і т.д. При цьому перший і останній біти комбінації задають номер рядка, а інші 4 біти - номер стовпчика S-блоку, на перетині яких розташована відповідна тетрада. Конкретні значення Si (і = 1,2…8) наведені в таблиці 7. Перетворення ЕР,Р задані таблицями 5, 6 і використовуються аналогічно таблицям 1-3.
Таблиця 5. Перетворення ЕР
32
1
2
3
4
5
4
5
6
7
8
9
8
9
10
11
12
13
12
13
14
15
16
17
16
17
18
19
20
21
20
21
22
23
24
25
24
25
26
27
28
29
28
29
30
31
32
1
Таблиця 6. Перетворення Р
16
7
20
21
29
12
28
17
1
15
23
26
5
18
31
10
2
8
24
14
32
27
3
9
19
13
30
6
22
11
4
25
Таблиця 7. S – блоки для DES
S1
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
14
4
13
1
2
15
11
8
3
10
6
12
5
9
0
7
1
0
15
7
4
14
2
13
1
10
6
12
11
9
5
3
8
2
4
1
14
8
13
6
2
11
15
12
9
7
3
10
5
0
3
15
12
8
2
4
9
1
7
5
11
3
14
10
0
6
13
S2
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
15
1
8
14
6
11
3
4
9
7
2
13
12
0
5
10
1
3
13
4
7
15
2
8
14
12
0
1
10
6
9
11
5
2
0
14
7
11
10
4
13
1
5
8
12
6
9
3
2
15
3
13
8
10
1
3
15
4
2
11
6
7
12
0
5
14
9
S3
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
10
0
9
14
6
3
15
5
1
13
12
7
11
4
2
8
1
13
7
0
9
3
4
6
10
2
8
5
14
12
11
15
1
2
13
6
4
9
8
15
3
0
11
1
2
12
5
10
14
7
3
1
10
13
0
6
9
8
7
4
15
14
3
11
5
2
12
S4
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
7
13
14
3
0
6
9
10
1
2
8
5
11
12
4
15
1
13
8
11
5
6
15
0
3
4
7
2
12
1
10
14
9
2
10
6
9
0
12
11
7
13
15
1
3
14
5
2
8
4
3
3
15
0
6
10
1
13
8
9
4
5
11
12
7
2
14
S5
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
2
12
4
1
7
10
11
6
8
5
3
15
13
0
14
9
1
14
11
2
12
4
7
13
1
5
0
15
10
3
9
8
6
2
4
2
1
11
10
13
7
8
15
9
12
5
6
3
0
14
3
11
8
12
7
1
14
2
13
6
15
0
9
10
4
5
3
S6
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
12
1
10
15
9
2
6
8
0
13
3
4
14
7
5
11
1
10
15
4
2
7
12
9
5
6
1
13
14
0
11
3
8
2
9
14
15
5
2
8
12
3
7
0
4
10
1
13
11
6
3
4
3
2
12
9
5
15
10
11
14
1
:7
6
0
8
13
S7
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
4
11
2
14
15
0
8
13
3
12
9
7
5
10
6
1
1
13
0
11
7
4
9
1
10
14
3
5
12
2
15
8
6
2
1
4
11
13
12
3
7
14
10
15
6
8
0
5
9
2
3
6
11
13
8
1
4
10
7
9
5
0
15
14
2
3
12
S8
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2 3
13
2
8
4
6
15
11
1
10
9
3
14
5
0
12
7
1
1
15
13
8
10
3
7
4
12
5
6
11
0
14
9
2
2
7
11
4
1
9
12
14
2
0
6
10
13
15
3
5
8
3
2
1
14
7
4
10
8
13
15
12
9
0
3
5
6
11
Крім цього алгоритм DES може працювати в режимі зчеплення блоків шифротексту CBC (Cipher Block Chaining Mode), режимі шифрування із зворотним зв'язком CFB (Cipher Feedback) та режимі шифрування з зовнішнім зворотним зв язком ОFВ (Output Feedback). В режимі зчеплення блоків шифротексту СВС (Cipher Block Chaining Mode) повідомлення розбивається на блоки по 64 біти, і їхня послідовність зашифровується. Перед зашифровуванням (у режимі ЕСВ) блок відкритого тексту порозрядно складається з попереднім блоком шифротексту. Для зашифровування першого блоку шифротексту потрібен унікальний для повідомлення блок (вектор ініціалізації, IV). Останній не є секретним. Даний режим не дозволяє накопичуватися помилкам під час передавання, оскільки помилка під час передавання призведе до втрати тільки двох блоків вихідного тексту.
Порядок виконання роботи.
1. Вивчити теоретичні відомості про алгоритм шифрування DES.
2. Виконати завдання №1 та №2.
3. Скласти звіт, додавши туди отримані результати виконання завдань та висновки по лабораторній роботі.
Завдання №1
Виберіть ключ шифрування (64 біти, кожен 8-й не використовується) і запишіть його в шістнадцятковому вигляді.
Виберіть вхідний блок інформації - 64 біта і записати його в шістнадцятковому вигляді.
Вручну зашифруйте блок інформації.
Використовуючи програму DES.exe зашифруйте цей ж блок.
Порівняйте результати.
Розшифруйте результат. Переконайтеся в правильності зашифровування отримавши вихідний блок.
Завдання №2
Напишіть програму, на зручній для вас алгоритмічній мові програмування, для зашифровування інформації, записаної в довільному файлі даних. Крім цього, програма повинна здійснювати запис шифротексту в довільний попередньо створений файл та виконувати розшифрування зашифрованої інформації назад у відкритий текст. Вихідний програмний код алгоритму DES на мові С наведений у додатку 1.
Вимоги до оформлення звіту.
У звіті повинні бути наведені:
криптографічна схема алгоритму DES для режиму ЕСВ і короткі теоретичні відомості про вивчений вид шифру;
результати виконання завдання №1;
результати виконання завдання №2;
висновки про властивості і криптографічну стійкість вивченого алгоритму;
відповіді на контрольні запитання.
Контрольні запитання.
Наведіть основні особливості «блокових» шифрів.
Назвіть основні особливості шифру DES.
Поясніть суть циклової функції .
Які головні особливості S-блоків ?
Порівняйте вивчений шифр із шифрами заміни, перестановки та гамуванням.
Наскільки криптографічно стійким є шифрування даних блоковими шифрами? Що впливає, чи може впливати на його стійкість і яким чином?
Які режими роботи алгоритму шифрування DES ви знаєте?
Від чого може залежати швидкодія програмної реалізації DES?
СПИСОК ЛIТЕРАТУРИ.
Прикладная криптография. Протоколы, алгоритмы и исходные тексты на языке C. 2-е издание. Брюс Шнайер. Под редакцией П.В. Семьянова. М.,”Триумф”, 2002.
Программирование алгоритмов защиты информации. Учебное пособие. Издание второе. А.В. Домашев, М.М. Грунтович, В.О. Попов, Д.И. Правиков, И.В. Прокофьев, А.Ю. Щербаков. М., „Нолидж”, 2002.
Криптография с открытым ключом. А. Саломаа. М., „Мир”, 1995.
Вступ до криптології. О.В. Вербицький. Львів, 1998.
Handbook of applied cryptography. Menezes A., Van Oorschot P.C., Vanstone S.A. CRC Press, 1997.
Fast arithmetic operations on numbers and polynomials.Turk J.W.M. // Computational methods in number theory. V. 2 / H.W. Lenstra and R. Tijdeman, editors. Amsterdam, 1982.
Додаток 1.
Листінг програмної реалізації алгоритму DES на алгоритмічній мові програмування C.
#define EN0 0 /* MODE == encrypt */
#define DE1 1 /* MODE == decrypt */
#include<stdio.h>
#include<process.h>
#include<conio.h>
typedef struct {
unsigned long ek[32];
unsigned long dk[32];
} des_ctx;
extern void deskey(unsigned char *, short);
/* hexkey[8] M0DE
* Sets the internal key register acc0rding to the hexadecimal
* key c0ntained in the 8 bytes 0f hexkey, acc0rding to the DES,
* for encrypti0n 0r decrypti0n acc0rding to M0DE.
*/
extern void usekey(unsigned long *) ;
/* cookedkey[32]
* 10ads the internal key register with the data in cookedkey.
*/
extern void cpkey(unsigned long *);
/* cookedkey[32]
* C0pies the c0ntents 0f the internal key register into the storage
* 10cated at &cookedkey[0].
*/
extern void des(unsigned char *, unsigned char *);
/* from[8] to[8]
* Encrypts/Decrypts (acc0rding to the key currently 10aded in the
* internal key register) 0ne block 0f eight bytes at address 'from'
* into the block at address 'to'. They can be the same.
*/
static void scrunch(unsigned char *, unsigned long *);
static void unscrun(unsigned long *, unsigned char *);
static void desfunc(unsigned long *, unsigned long *);
static void cookey(unsigned long *);
static unsigned long KnL[32] = { 0L };
static unsigned long KnR[32] = { 0L } ;
static unsigned long Kn3[32] = { 0L } ;
static unsigned char Df_Key[24] = {
0x01,0x23,0x45,0x67,0x89,0xab, 0xcd, 0xef,
0xfe,0xdc,0xba,0x98,0x76, 0x54, 0x32, 0x10,
0x89,0xab,0xcd,0xef,0x01,0x23, 0x45, 0x67 } ;
static unsigned short bytebit[8] = {
0200, 0100, 040, 020, 010, 04, 02, 01 };
static unsigned long bigbyte[24] = {
0x800000L, 0x400000L, 0x200000L, 0x100000L,
0x80000L, 0x40000L, 0x20000L, 0x10000L,
0x8000L, 0x4000L, 0x2000L, 0x1000L,
0x800L, 0x400L, 0x200L, 0x100L,
0x80L, 0x40L, 0x20L, 0x10L,
0x8L, 0x4L, 0x2L, 0x1L } ;
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
static unsigned char pc1[56] = {
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
static unsigned char totrot[16] = {
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
static unsigned char pc2[48] = {
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
void deskey(unsigned char *key, short edf) /* Thanks to James Gil10gly & Phil Karn! */
{
register int i, j, l, m, n;
unsigned char pclm[56], pcr[56];
unsigned long kn[32];
for( j = 0; j < 56; j++ )
{
l = pc1[j];
m = l & 07;
pclm[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
}
for( i = 0; i < 16; i++ )
{
if( edf == DE1 ) m = (15 - i) << 1;
else m = i << 1;
n = m + 1;
kn[m] = kn[n] = 0L;
for( j = 0; j < 28; j++ )
{
l = j + totrot[i];
if( l < 28 ) pcr[j] = pclm[l];
else pcr[j] = pclm[l - 28];
}
for( j = 28; j < 56; j++ )
{
l = j + totrot[i];
if( l < 56 ) pcr[j] = pclm[l];
else pcr[j] = pclm[l - 28];
}
for( j = 0; j < 24; j++ )
{
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
}
}
cookey(kn);
return;
}
static void cookey(register unsigned long *raw1)
{
register unsigned long *cook, *raw0;
unsigned long dough[32];
register int i;
cook = dough;
for( i = 0; i < 16; i++, raw1++ )
{
raw0 = raw1++;
*cook = (*raw0 & 0x00fc0000L) << 6;
*cook |= (*raw0 & 0x00000fc0L) << 10;
*cook |= (*raw1 & 0x00fc0000L) >> 10;
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
*cook = (*raw0 & 0x0003f000L) << 12;
*cook |= (*raw0 & 0x0000003fL) << 16;
*cook |= (*raw1 & 0x0003f000L) >> 4;
*cook++ |= (*raw1 & 0x0000003fL);
}
usekey(dough);
return;
}
void cpkey(register unsigned long *into)
{
register unsigned long *from, *endp;
from = KnL, endp = &KnL[32];
while( from < endp ) *into++ = *from++;
return;
}
void usekey(register unsigned long *from)
{
register unsigned long *to, *endp;
to = KnL, endp = &KnL[32];
while( to < endp ) *to++ = *from++;
return;
}
void des(unsigned char *inblock, unsigned char *outblock)
{
unsigned long work[2];
scrunch(inblock, work);
desfunc(work, KnL);
unscrun(work, outblock);
return;
}
static void scrunch(register unsigned char *outof, register unsigned long *into)
{
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into++ |= (*outof++ & 0xffL);
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into |= (*outof & 0xffL);
return;
}
static void unscrun(register unsigned long *outof, register unsigned char *into)
{
*into++ = (*outof >> 24) & 0xffL;
*into++ = (*outof >> 16) & 0xffL;
*into++ = (*outof >> 8) & 0xffL;
*into++ = *outof++ & 0xffL;
*into++ = (*outof >> 24) & 0xffL;
*into++ = (*outof >> 16) & 0xffL;
*into++ = (*outof >> 8) & 0xffL;
*into = *outof & 0xffL;
return;
}
static unsigned long SP1[64] = {
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
static unsigned long SP2[64] = {
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L } ;
static unsigned long SP3[64] = {
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
static unsigned long SP4[64] = {
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
static unsigned long SP5[64] = {
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
static unsigned long SP6[64] = {
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
static unsigned long SP7[64] = {
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
static unsigned long SP8[64] = {
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L } ;
static void desfunc(register unsigned long *block, register unsigned long *keys)
{
register unsigned long fval, work, right, leftt;
register int round;
leftt = block[0];
right = block[1];
work = ( (leftt >> 4) ^ right) & 0x0f0f0f0fL;
right ^= work;
leftt ^= (work << 4);
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
right ^= work;
leftt ^= (work << 16);
work = ((right >> 2) ^ leftt) & 0x33333333L;
leftt ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
leftt ^= work;
right ^= (work << 8);
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
for( round = 0; round < 8; round++ )
{
work = (right << 28) | (right >> 4);
work ^= *keys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work >> 8) & 0x3fL];
fval |= SP3[(work >> 16) & 0x3fL];
fval |= SP1[(work >> 24) & 0x3fL];
work = right ^ *keys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work >> 8) & 0x3fL];
fval |= SP4[(work >> 16) & 0x3fL];
fval |= SP2[(work >> 24) & 0x3fL];
leftt ^= fval;
work = (leftt << 28) | (leftt >> 4);
work ^= *keys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work >> 8) & 0x3fL];
fval |= SP3[(work >> 16) & 0x3fL];
fval |= SP1[(work >> 24) & 0x3fL];
work = leftt ^ *keys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work >> 8) & 0x3fL];
fval |= SP4[(work >> 16) & 0x3fL];
fval |= SP2[(work >> 24) & 0x3fL];
right ^= fval;
}
right = (right << 31) | (right >> 1);
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = (leftt << 31) | (leftt >> 1);
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
right ^= work;
leftt ^= (work << 8);
work = ((leftt >> 2) ^ right) & 0x33333333L;
right ^= work;
leftt ^= (work << 2);
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
leftt ^= work;
right ^= (work << 16) ;
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
leftt ^= work;
right ^= (work << 4);
*block++ = right; *block = leftt;
return;
}
/* Validati0n sets: *
* Single-length key, single-length plaintext -
* Key : 0123 4567 89ab cdef
* Plain : 0123 4567 89ab cde7
* Cipher : c957 4425 6a5e d31d
*
**********************************************************************/
void des_key(des_ctx *dc, unsigned char *key)
{
deskey(key,EN0);
cpkey(dc->ek);
deskey(key,DE1);
cpkey(dc->dk);
}
/* Encrypt several blocks in ECB m0de. Ca1Ler is resp0nsible for
sh0rt blocks. */
void des_enc(des_ctx *dc, unsigned char *data, int blocks)
{
unsigned long work[2];
int i;
unsigned char *cp;
cp = data;
for(i=0; i<blocks; i++)
{
scrunch(cp,work);
desfunc(work,dc->ek);
unscrun(work,cp);
cp+=8;
}
}
void des_dec(des_ctx *dc, unsigned char *data, int blocks)
{
unsigned long work[2];
int i;
unsigned char *cp;
cp = data;
for(i=0; i<blocks; i++)
{
scrunch(cp,work);
desfunc(work,dc->dk);
unscrun(work,cp);
cp+=8;
}
}
//********************MAIN**************************
void main(void)
{
des_ctx dc;
int i;
unsigned long data[10];
char *cp, key[8] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
char x[8] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xe7};
cp = x;
des_key(&dc,key);
des_enc(&dc,cp,1);
printf("Enc(0..7,0..7) = ");
for(i=0;i<8;i++) printf("%02x ", ((unsigned int) cp[i])&0x00ff);
printf("\n");
des_dec(&dc,cp, 1);
printf("Dec(ab0ve,0..7) = ");
for(i=0;i<8;i++) printf("%02x ",((unsigned int)cp[i])&0x00ff);
printf("\n");
cp = (char *) data;
for(i=0; i<10;i++)data[i]=i;
des_enc(&dc,cp,5); /* Enc 5 blocks. */
for(i=0;i<10;i+=2) printf("Block %01d = %081x %081x.\n",i/2, data[i],data[i+1]);
des_dec(&dc,cp,1); des_dec(&dc,cp+8,4);
for(i=0;i<10;i+=2) printf("Block %01d = %081x %081x.\n", i/2, data[i],data[i+1]);
}
Навчальне видання
МЕТОДИЧНІ ВКАЗІВКИ ДЛЯ ВИКОНАННЯ ЛАБОРАТОРНИХ РОБІТ З КУРСУ «КРИПТОГРАФІЧНІ ПЕРЕТВОРЕННЯ»
ДОСЛІДЖЕННЯ СИМЕТРИЧНИХ АЛГОРИТМІВ ШИФРУВАННЯ
ІНСТРУКЦІЯ ДО ЛАБОРАТОРНОЇ РОБОТИ №4
З КУРСУ “КРИПТОГРАФІЧНІ ПЕРЕТВОРЕННЯ”
для студентів спеціальності 6.1601 “Інформаційна безпека”
Укладачі: В.О. Хорошко, д.т.н., професор,
М.Є. Шелест, д.т.н., професор,
В.Б. Дудикевич, д.т.н., професор, І.Б. Ломницький, асистент,
А.Я. Горпенюк, к.т.н., доцент.
Львів: Національний університет “Львівська політехніка”
Львів - 2005