МИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ, СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ Ордена Трудового Красного Знамени Федеральное государственное бюджетное образовательное учреждение высшего образования Московский технический университет связи и информатики (МТУСИ) Кафедра «Информационная безопасность» Отчёт по дисциплине «Криптографические методы защиты информации» Выполнили студенты группы БИБ1802 Пеев Д.Д. Попкова Е.Д. Таганов Н.С. Москва, 2021 Лабораторная работа №1 «Простые симметричные шифры» Цель работы: Ознакомление с простыми симметричными криптографическими шифрами. Теоретическая часть Симметричные алгоритмы Среди алгоритмов шифрования, основанных на ключах существует два основных типа: симметричные и ассиметричные. Шифрование открытого сообщения m с помощью некоторой функции шифрования E на ключе 𝒌𝟏 в результате чего получается шифрованный текст с, принято обозначать так: 𝑬𝒌𝟏 (𝒎) = 𝒄 Дешифрование шифрованного текста с с помощью некоторой функции дешифрования D на ключе 𝒌𝟐 , в результате чего получается открытое сообщение m, обозначается следующим образом: 𝑫𝒌𝟐 (𝒄) = 𝒎 В случае, когда 𝒌𝟏 = 𝒌𝟐 - шифр называется симметричным, в противном же случае – ассимметричным. Подстановочные шифры Подстановочным шифром называется шифр, который каждый символ открытого текста в шифротексте заменяет другим символом. Получатель инвертирует подстановку шифротекста, восстанавливая открытый текст. В классической криптографии существует четыре типа подстановочных шифров: 1. Простой подстановочный шифр, или моноалфавитный шифр, - это шифр, который каждый символ 2 открытого текста заменяет соответствующим символом шифротекста. Простыми подстановочными шифрами являются криптограммы в газетах. 2. Однозвучный подстановочный шифр похож на простую подстановочную криптосистему за исключением того, что один символ открытого текста отображается на несколько символов шифротекста. Например, "A" может соответствовать 5, 13, 25 или 56, "B" - 7, 19, 31 или 42 и так далее. 3. Полиграммный подстановочный шифр - это шифр, который блоки символов шифрует по группам. Например, "ABA" может соответствовать "RTQ", "ABB" может соответствовать "SLL" и так далее. 4. Полиалфавитный подстановочный шифр состоит из нескольких простых подстановочных шифров. Например, могут быть использованы пять различных простых подстановочных фильтров; каждый символ открытого текста заменяется с использованием одного конкретного шифра. Перестановочные шифры В перестановочном шифре меняется не открытый текст, а порядок символов. В простом столбцовом перестановочном шифре открытый текст пишется горизонтально на разграфленном листе бумаги фиксированной ширины, а шифротекст считывается по вертикали. Дешифрирование представляет собой запись шифротекста вертикально на листе разграфленной бумаги фиксированной ширины и затем считывание открытого текста горизонтально. 3 Реализация заданий Задание 1: Придумать свой перестановочный шифр, реализовать его на любом языке программирования, зашифровать с помощью произвольное сообщение, после чего дешифровать его. Рисунок 1. Идея реализации задания №1. #include <math.h> #include <string> #include <iostream> using namespace std; int Key(string); int length(string message) { int len = message.length(); return len; } int comparing_numbers(string message) { int len = length(message); double D_check_len = sqrt(len); int I_check_len = sqrt(len); if (D_check_len != I_check_len) { I_check_len++; } return I_check_len; } int Encryption_Decryption(string message, char** Key_Matrix) { int len = length(message); int key_size = comparing_numbers(message); int n = key_size, m = n; cout << endl << "Encrypted/Decryption message: "; for (int j = 0; j < m; j++) for (int i = 0; i < n; i++) { cout << Key_Matrix[i][j]; } cout << endl; return 0; 4 шифра } int Key(string message) { char Getting_a_string[1000]; int len = length(message); int key_size = comparing_numbers(message); strcpy(Getting_a_string, message.c_str()); int n = key_size; int m = n; char** Key_Matrix; Key_Matrix = new char* [n]; for (int i = 0; i < n; i++) { Key_Matrix[i] = new char[m]; } int k = 0, end_str = 0; for (int i = 0; i < n; i++) for (int j = 0, enter = 0; j < m; j++, k++, enter++, end_str++) { if (end_str != len && end_str < len) { if (enter == 5) { Key_Matrix[i][j] = Getting_a_string[k]; } else { Key_Matrix[i][j] = Getting_a_string[k]; } } else { Key_Matrix[i][j] = ' '; } } Encryption_Decryption(message, Key_Matrix); return 0; } int main() { string message; cout << "Enter a message: "; getline(cin, message); // "This text must be encrypted" Key(message); return 0; } Листинг 1. Перестановочный шифр Рисунок 2. Шифрование. Перестановочный шифр. 5 Рисунок 3. Дешифровка. Перестановочный шифр. Задание 2: Придумать свой простой подстановочный шифр (моноалфавитный шифр), реализовать его на любом языке программирования, зашифровать с помощью шифра произвольное сообщение, после чего дешифровать. Идея шифра заключается в том, что исходное сообщение шифруется с помощью таблицы ASCII. К коду буквы исходного текста (ИТ) прибавляется 5. На выходе мы получаем символ равный «код буквы ИТ+5». #include <math.h> #include <string> #include <iostream> using namespace std; int length(string message) { int len = message.length(); return len; } string Entering_message() { string message; getline(cin, message); return message; } void Encryption() { string message = Entering_message(); int len = message.length(); char Getting_a_string[1000]; strcpy(Getting_a_string, message.c_str()); char* Key_Matrix; Key_Matrix = new char[len]; for (int i = 0, k = 0; i < len; i++, k++) { Key_Matrix[i] = Getting_a_string[k]; } for (int i = 0; i < len; i++) 6 { if (Key_Matrix[i] == ' ') { cout << Key_Matrix[i]; } else { Key_Matrix[i] += 5; cout << Key_Matrix[i]; } } } void Decryption() { { string message = Entering_message(); int len = message.length(); char Getting_a_string[1000]; strcpy(Getting_a_string, message.c_str()); char* Key_Matrix; Key_Matrix = new char[len]; for (int i = 0, k = 0; i < len; i++, k++) { Key_Matrix[i] = Getting_a_string[k]; } for (int i = 0; i < len; i++) { if (Key_Matrix[i] == ' ') { cout << Key_Matrix[i]; } else { Key_Matrix[i] -= 5; cout << Key_Matrix[i]; } } }} int main() { cout << "--Encryption--\n"; Encryption(); cout << endl << endl; cout << "--Decryption--\n"; Decryption(); cout << endl << endl; return 0; } Листинг 2. Простой подстановочный шифр (моноалфавитный шифр). 7 Рисунок 4. Шифрование и дешифровка. Простой подстановочный шифр (моноалфавитный шифр). Задание 3: Придумать свой однозвучный подстановочный шифр, реализовать его на любом языке программирования, зашифровать с помощью шифра произвольное сообщение, после чего дешифровать его. 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 46 41 29 67 1 19 96 76 95 30 72 18 43 75 2 49 17 36 81 61 87 93 92 86 66 40 64 77 79 25 71 53 24 82 32 37 89 48 45 38 62 20 10 27 68 60 35 16 8 63 11 21 #include <math.h> #include <string> #include <iostream> #include <ctime> using namespace std; string Key_Matrix[3][27] = {...} int length(string message) { int len = message.length(); return len; } string Entering_message() { cout << "Original message: "; string message; getline(cin, message); return message; } void Encryption() { string check; string message = Entering_message(); int len = message.length(); cout << "Encrypted message: "; for (int i = 0, k = 0; i < len; i++, k++) { check = message[k]; for (int j = 0; j < 27; j++) { 8 if (check == Key_Matrix[0][j]) { int random_j = 1 + rand() % 2; cout << Key_Matrix[random_j][j]<< " "; } } } cout << "\n\n"; } void Decrypted() { string Dmass[30]; int cipher = 1, dm=0; cout << "Encrypted message: "; while (cipher != 0) { cin >> cipher; string s_cipher = to_string(cipher); for (int j = 0; j < 27; j++) for(int i=1; i<3; i++) { if (s_cipher == Key_Matrix[i][j]) { Dmass[dm] = Key_Matrix[0][j]; dm++; i = 3; j = 27; } } } cout << "Decrypted message: "; for (int i = 0; i < 30; i++) { cout << Dmass[i] << " "; } cout << endl; } int main() { Encryption(); Decrypted(); } Листинг 3. Однозвучный подстановочный шифр. Рисунок 5. Шифрование и дешифровка. Однозвучный подстановочный шифр. 9 Задание 4: Придумать полиграммный подстановочный шифр, реализовать его на любом языке программирования, зашифровать с помощью шифра произвольное сообщение, после чего дешифровать его. Исходная строка разбивается на блоки, по 3 буквы в каждом. После этого, с помощью рандомайзера, генерируются блоки-шифр и выводятся на экран. #include <math.h> #include <string> #include <iostream> using namespace std; int length(string message) { int len = message.length(); return len; } string Entering_message() { cout << "Original message: "; string message; getline(cin, message); return message; } void Decryption(string** Key_Matrix) { string block, message; string** Encrypted_Matrix; cout << "Encrypted message: "; getline(cin, message); int len = message.length(); int n = len / 3; float cn = len % 3; if (cn != 0) { n++; } Encrypted_Matrix = new string * [n]; for (int i = 0; i < n; i++) { Encrypted_Matrix[i] = new string[1]; } cout << "Original message: "; for (int i = 0, b = 0; i < n; b += 3, i++) { block = message[b]; block += message[b + 1]; block += message[b + 2]; for (int j = 0, b = 0; j < 1; j++) { 10 Encrypted_Matrix[i][j] = block; } } for (int j = 0; j < 1; j++) for (int i = 0; i < n; i++) { for (int k = 0; k < n; k++) { if (Encrypted_Matrix[i][j] == Key_Matrix[k][0]) { cout << Key_Matrix[k][1]; } } } } int Encryption(string message) { int len = length(message), random; string block; string** Original_Matrix; string** Сipher_Matrix; string** Key_Matrix; int n = len / 3; float cn = len % 3; if(cn != 0){n++;} Original_Matrix = new string* [n]; for (int i = 0; i < n; i++) { Original_Matrix[i] = new string[1]; } for (int i = 0, b = 0; i < n; b += 3, i++) { block = message[b]; if (message[b + 1] == '\0') { block += message[b + 1]; block += " "; } else { block += message[b + 1]; block += message[b + 2]; } for (int j = 0, b = 0 ; j < 1; j++) { Original_Matrix[i][j] = block; } } cout << "Encrypted message: "; Сipher_Matrix = new string * [n]; for (int i = 0; i < n; i++) { Сipher_Matrix[i] = new string[1]; } for (int i = 0, b = 0; i < n; b += 3, i++) { block = char('a' + rand() % ('z' - 'a')); block += char('a' + rand() % ('z' - 'a')); block += char('a' + rand() % ('z' - 'a')); 11 for (int j = 0, b = 0; j < 1; j++) { Сipher_Matrix[i][j] = block; cout << Сipher_Matrix[i][j]; } } Key_Matrix = new string * [n]; for (int i = 0; i < n; i++) { Key_Matrix[i] = new string[2]; } for (int j = 0; j < 2; j++) { for (int i = 0; i < n; i++) { if (j == 0) { Key_Matrix[i][j] = Сipher_Matrix[i][0]; } else { Key_Matrix[i][j] = Original_Matrix[i][0]; } } } cout << "\n\n"; Decryption(Key_Matrix); return 0; } int main() { string message = Entering_message(); Encryption(message); cout << "\n\n"; } Листинг 4. Полиграммный подстановочный шифр. Рисунок 6. Шифрование и дешифровка. Полиграммный подстановочный шифр. 12 Задание 5: Придумать полиалфавитный подстановочный шифр, реализовать его на любом языке программирования, зашифровать с помощью шифра произвольное сообщение, после чего дешифровать его. 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 a 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 b 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 a c c d e f g h i j k l m n o p q r s t u v w x y z a b d d e f g h i j k l m n o p q r s t u v w x y z a b c e e f g h i j k l m n o p q r s t u v w x y z a b c d f f g h i j k l m n o p q r s t u v w x y z a b c d e g g h i j k l m n o p q r s t u v w x y z a b c d e f h h i j k l m n o p q r s t u v w x y z a b c d e f g i i j k l m n o p q r s t u v w x y z a b c d e f g h j j k l m n o p q r s t u v w x y z a b c d e f g h i k k l m n o p q r s t u v w x y z a b c d e f g h i j l l m n o p q r s t u v w x y z a b c d e f g h i j k m m n o p q r s t u v w x y z a b c d e f g h i j k l n n o p q r s t u v w x y z a b c d e f g h i j k l m o o p q r s t u v w x y z a b c d e f g h i j k l m n p p q r s t u v w x y z a b c d e f g h i j k l m n o q q r s t u v w x y z a b c d e f g h i j k l m n o p r r s t u v w x y z a b c d e f g h i j k l m n o p q s s t u v w x y z a b c d e f g h i j k l m n o p q r t t u v w x y z a b c d e f g h i j k l m n o p q r s u u v w x y z a b c d e f g h i j k l m n o p q r s t v v w x y z a b c d e f g h i j k l m n o p q r s t u w w x y z a b c d e f g h i j k l m n o p q r s t u v x x y z a b c d e f g h i j k l m n o p q r s t u v w y y z a b c d e f g h i j k l m n o p q r s t u v w x z z 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 Для данного алгоритма нам потребуется ключ. Самая верхняя строка по вертикали предназначена для ключа, самый левый столбец для исходного сообщения. Для шифрования находим пересечение буквы из самой верхней строки и самого левого столбца. #include #include #include #include <math.h> <string> <iostream> <ctime> using namespace std; char Key_Matrix[27][27] = {...} 13 int length(string message) { int len = message.length(); return len; } string Entering_Key() { cout << "Key: "; string key; getline(cin, key); return key; } string Entering_message() { cout << "Original message: "; string message; getline(cin, message); return message; } void Encryption(string key) { int ie, je; string message = Entering_message(); int len = message.length(); int len_k = key.length(); while (len_k != len) { cout<< endl << "Error: The key and message lengths must be the same\n"; message = Entering_message(); len = message.length(); } cout << "Encrypted message: "; for (int i = 0; i < len; i++) { for (int j = 1; j < 27; j++) { if (key[i] == Key_Matrix[0][j]) {ie = j;} if (message[i] == Key_Matrix[j][0]) {je = j;} } cout << Key_Matrix[ie][je]; } cout << "\n\n"; } void Decrypted(string key) { int k=1; string message = Entering_message(); int len = message.length(); int len_k = key.length(); while (len_k != len) { cout << endl << "Error: The key and message lengths must be the same\n"; message = Entering_message(); len = message.length(); } cout << "Decrypted message: "; for (int i = 0; i < len; i++) 14 { for (int j = 1; j < 27; j++) { if (key[i] == Key_Matrix[0][j]) { while (message[i] != Key_Matrix[k][j]) { k++; } } } cout << Key_Matrix[k][0]; k = 1; } cout << "\n\n"; } int main() { string key = Entering_Key(); Encryption(key); Decrypted(key); } Листинг 5. Полиалфавитный подстановочный шифр. Рисунок 7. Шифрование и дешифровка. полиалфавитный подстановочный шифр. Задание 6: Известно, что сообщение "Pbatenghyngvbaf! Vg'f n Pnrfne pvcure!" было зашифровано шифром Цезаря, но ключ k неизвестен. Написать вспомогательную программу, которая поможет в расшифровке этого сообщения. #include <string> #include <iostream> using namespace std; int main(){ string message = "Pbatenghyngvbaf! Vg'f n Pnrfne pvcure!"; int len = message.length(); for (int key = 1; key < 26; key++) 15 { cout << "Key(" << key << "): "; for (int j = 0; j < len; j++) { char c = message[j]; char first = 0; if (c >= 'a' && c <= 'z') first = 'a'; else if (c >= 'A' && c <= 'Z') first = 'A'; if (first != 0) c = first + (c - first - key + 26) % 26; cout << c; } cout << endl; } return 0; } Листинг 6. Дешифровка сообщения. Рисунок 8. Нахождение нужного ключа. Задание 7: Реализуйте собственный аналог функции ROT13 его на любом языке программирования, зашифруйте с помощью вашего шифра произвольное сообщение, после чего дешифруйте его. Опишите достоинства и недостатки шифра. #include <string> #include <iostream> using namespace std; int length(string message) { int len = message.length(); 16 return len; } string Entering_message() { cout << "Original message: "; string message; getline(cin, message); return message; } void Encryption_Decryption() { string message = Entering_message(); int len = message.length(), key = 13; cout << "Encrypted message: "; for (int j = 0; j < len; j++) { char c = message[j]; char first = 0; if (c >= 'a' && c <= 'z') first = 'a'; else if (c >= 'A' && c <= 'Z') first = 'A'; if (first != 0) cout << (c = first + (c - first + key + 26) % 26); } cout << "\n\n"; message = Entering_message(); len = message.length(); cout << "Decrypted message: "; for (int j = 0; j < len; j++) { char c = message[j]; char first = 0; if (c >= 'a' && c <= 'z') first = 'a'; else if (c >= 'A' && c <= 'Z') first = 'A'; if (first != 0) cout << (c = first + (c - first - key + 26) % 26); } cout << "\n"; } int main() { Encryption_Decryption(); return 0; } Листинг 7. ROT13. Рисунок 9. Шифрование и дешифровка. ROT13. 17 Вывод Мы ознакомились с простыми симметричными криптографическими шифрами. Узнали какие виды этого шифра бывают и написали свои алгоритмы для их реализации на языке С++. 18 Список литературы 1. Простейшие методы шифрования с закрытым ключом // Интерактивная система обучения URL: https://emkelektron.webnode.com/news/metody- shifrovaniya-zamenoj-podstanovkoj/ (дата обращения: 13.09.2021). 2. Полиалфавитный шифр // FANDOM control.fandom.com/wiki/Полиалфавитный_шифр URL: (дата https://mindобращения: 14.09.2021). 3. Классический криптоанализ // Habr URL: https://habr.com/ru/post/271257/ (дата обращения: 14.09.2021). 19