From c86e103352a221a5e1056e446bd9846bd8a5c130 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:39:48 +0400 Subject: [PATCH 1/9] updated according to comments, added final_text --- final_text.txt | 1 + settings.json | 13 +++++++++++ task1.py | 45 ++++++++++++++++++++++++++++++++++++ task2.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ work_files.py | 40 ++++++++++++++++++++++++++++++++ 5 files changed, 161 insertions(+) create mode 100644 final_text.txt create mode 100644 settings.json create mode 100644 task1.py create mode 100644 task2.py create mode 100644 work_files.py diff --git a/final_text.txt b/final_text.txt new file mode 100644 index 00000000..2514fce0 --- /dev/null +++ b/final_text.txt @@ -0,0 +1 @@ +конфиденциальность самыи проработанныи у нас в стране аспект информационнои безопасностина страже конфиденциальности стоят законы нормативные акты многолетнии опыт соответствуьших служботечественные аппаратнопрограммные продукты позволяьт закрыть практически все потенциальные каналы утечки информациик сожалениь практическая реализация мер по обеспечениь конфиденциальности современных информационных систем наталкивается на серьезные трудностивопервых сведения о технических каналах утечки информации являьтся закрытыми так что большинство пользователеи лишено возможности составить полное представление о потенциальных рисках и степени их серьезностивовторых авторам не известны отечественные аппаратные реализации шифраторов с достаточным быстродеи ствием что накладывает ограничения на виды и объемы шифруемои информациипрограммные разработки охватываьт лишь часть распространенных компььтерных платформ \ No newline at end of file diff --git a/settings.json b/settings.json new file mode 100644 index 00000000..420e1891 --- /dev/null +++ b/settings.json @@ -0,0 +1,13 @@ +{ + "ALPHABET": "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ ", + "PLANE_TEXT": "plane_text.txt", + "KEY_ENCODE": "key_encode.json", + "ENCRYPTED": "cod5.txt", + "STANDARD": "standard_frequency.json", + "REAL_FREQ": "real_freq.json", + "DECRYPTED": "decrypted.txt", + "KEY_DECODE": "key_decode.json", + "KEY": "key_readable.json", + "TEXT": "final_text.txt", + "RESULT": "encoded.txt" +} \ No newline at end of file diff --git a/task1.py b/task1.py new file mode 100644 index 00000000..16398c8f --- /dev/null +++ b/task1.py @@ -0,0 +1,45 @@ +from work_files import * + + +def vigenere_cipher(text, key, alphabet) -> str: + text = text.upper() + key = key["key"] + + encoded_text = '' + key_index = 0 + + for char in text: + if char in alphabet: + char_pos = alphabet.index(char) + + key_char_pos = alphabet.index(key[key_index % len(key)]) + + new_pos = (char_pos + key_char_pos) % len(alphabet) + + encoded_text += alphabet[new_pos] + + key_index += 1 + else: + encoded_text += char + + return encoded_text + + +def main(): + try: + task1 = read_json("settings.json") + text = read_txt(task1["PLANE_TEXT"]) + key = read_json(task1["KEY_ENCODE"]) + alphabet = task1["ALPHABET"] + res = vigenere_cipher(text, key, alphabet) + write_txt(res, task1["RESULT"]) + print(res) + + except FileNotFoundError: + print("Ошибка: Файл не найден.") + except Exception as e: + print(f"Произошла ошибка: {e}") + +if __name__ == "__main__": + main() + diff --git a/task2.py b/task2.py new file mode 100644 index 00000000..290dd78e --- /dev/null +++ b/task2.py @@ -0,0 +1,62 @@ +from work_files import * + + +def real_frequency(text) -> dict: + frequency_dict = {} + length = len(text) + for char in text: + frequency_dict[char] = frequency_dict.get(char, 0) + 1 + for char in frequency_dict: + frequency_dict[char] = frequency_dict[char] / length + return dict(sorted(frequency_dict.items(), key=lambda item: item[1], reverse=True)) + + +def form_key(standard, real): + res = { + key1: key2 + for (key1, _), (key2, _) in zip(standard.items(), real.items()) + if key1 in standard and key2 in real + } + return res + + +def exchange(text, key) -> str: + decrypted = "" + for char in text: + decrypted_s = key.get(char) + if decrypted_s is None: + decrypted_s = char + decrypted += decrypted_s + return decrypted + + +def main(): + try: + task2 = read_json("settings.json") + text = read_txt(task2["ENCRYPTED"]) + + if text: + freq_dict = real_frequency(text) + write_json(freq_dict, (task2["REAL_FREQ"])) + print(freq_dict) + + sample_freq = read_json(task2["STANDARD"]) + new_dict = form_key(freq_dict, sample_freq) + write_json(new_dict, (task2["KEY_DECODE"])) + print(new_dict) + + res = exchange(text, new_dict) + write_txt(res, (task2["DECRYPTED"])) + print(res) + + read = exchange(res, read_json(task2["KEY"])) + write_txt(read, (task2["TEXT"])) + print(read) + + except FileNotFoundError: + print("Ошибка: Файл не найден.") + except Exception as e: + print(f"Произошла ошибка: {e}") + +if __name__ == "__main__": + main() diff --git a/work_files.py b/work_files.py new file mode 100644 index 00000000..cff0704a --- /dev/null +++ b/work_files.py @@ -0,0 +1,40 @@ +import json + + +def write_txt(data, filename) -> None: + try: + with open(filename, 'w', encoding='utf-8') as f: + f.write(data) + except Exception as e: + raise Exception(f"An error occurred when saving the file: {e}") + + +def read_txt(filename: str) -> str: + try: + with open(filename, 'r', encoding='utf-8') as file: + file = file.read().strip() + return file + except FileNotFoundError: + print(f"file {filename} not found") + except Exception as e: + print(f"error: {e}") + + +def read_json(filename: str) -> dict[str, str]: + try: + with open(filename, "r", encoding="utf-8") as file: + return json.load(file) + except FileNotFoundError: + print(f"file {filename} not found") + except json.JSONDecodeError: + print(f"file {filename} isn't correct JSON.") + except Exception as e: + print(f"error: {e}") + + +def write_json(dictionary, filename) -> None: + try: + with open(filename, 'w', encoding='utf-8') as file: + json.dump(dictionary, file, indent=4, ensure_ascii=False) + except Exception as e: + raise Exception(f"An error occurred when saving the file: {e}") \ No newline at end of file From 8a64c2d3006a4b8e1f0c69b8788dbe79204dcf52 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:46:32 +0400 Subject: [PATCH 2/9] Delete final_text.txt --- final_text.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 final_text.txt diff --git a/final_text.txt b/final_text.txt deleted file mode 100644 index 2514fce0..00000000 --- a/final_text.txt +++ /dev/null @@ -1 +0,0 @@ -конфиденциальность самыи проработанныи у нас в стране аспект информационнои безопасностина страже конфиденциальности стоят законы нормативные акты многолетнии опыт соответствуьших служботечественные аппаратнопрограммные продукты позволяьт закрыть практически все потенциальные каналы утечки информациик сожалениь практическая реализация мер по обеспечениь конфиденциальности современных информационных систем наталкивается на серьезные трудностивопервых сведения о технических каналах утечки информации являьтся закрытыми так что большинство пользователеи лишено возможности составить полное представление о потенциальных рисках и степени их серьезностивовторых авторам не известны отечественные аппаратные реализации шифраторов с достаточным быстродеи ствием что накладывает ограничения на виды и объемы шифруемои информациипрограммные разработки охватываьт лишь часть распространенных компььтерных платформ \ No newline at end of file From 094a80f8dba820574922a2dd4d4011c49ae718e3 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:47:41 +0400 Subject: [PATCH 3/9] Delete settings.json --- settings.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 settings.json diff --git a/settings.json b/settings.json deleted file mode 100644 index 420e1891..00000000 --- a/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "ALPHABET": "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ ", - "PLANE_TEXT": "plane_text.txt", - "KEY_ENCODE": "key_encode.json", - "ENCRYPTED": "cod5.txt", - "STANDARD": "standard_frequency.json", - "REAL_FREQ": "real_freq.json", - "DECRYPTED": "decrypted.txt", - "KEY_DECODE": "key_decode.json", - "KEY": "key_readable.json", - "TEXT": "final_text.txt", - "RESULT": "encoded.txt" -} \ No newline at end of file From 9d39620060593f970cd5ea4c54a83e00c958a280 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:47:57 +0400 Subject: [PATCH 4/9] Delete task1.py --- task1.py | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 task1.py diff --git a/task1.py b/task1.py deleted file mode 100644 index 16398c8f..00000000 --- a/task1.py +++ /dev/null @@ -1,45 +0,0 @@ -from work_files import * - - -def vigenere_cipher(text, key, alphabet) -> str: - text = text.upper() - key = key["key"] - - encoded_text = '' - key_index = 0 - - for char in text: - if char in alphabet: - char_pos = alphabet.index(char) - - key_char_pos = alphabet.index(key[key_index % len(key)]) - - new_pos = (char_pos + key_char_pos) % len(alphabet) - - encoded_text += alphabet[new_pos] - - key_index += 1 - else: - encoded_text += char - - return encoded_text - - -def main(): - try: - task1 = read_json("settings.json") - text = read_txt(task1["PLANE_TEXT"]) - key = read_json(task1["KEY_ENCODE"]) - alphabet = task1["ALPHABET"] - res = vigenere_cipher(text, key, alphabet) - write_txt(res, task1["RESULT"]) - print(res) - - except FileNotFoundError: - print("Ошибка: Файл не найден.") - except Exception as e: - print(f"Произошла ошибка: {e}") - -if __name__ == "__main__": - main() - From d18527ae57d097c198a61e62ed935120b4840fa0 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:48:11 +0400 Subject: [PATCH 5/9] Delete task2.py --- task2.py | 62 -------------------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 task2.py diff --git a/task2.py b/task2.py deleted file mode 100644 index 290dd78e..00000000 --- a/task2.py +++ /dev/null @@ -1,62 +0,0 @@ -from work_files import * - - -def real_frequency(text) -> dict: - frequency_dict = {} - length = len(text) - for char in text: - frequency_dict[char] = frequency_dict.get(char, 0) + 1 - for char in frequency_dict: - frequency_dict[char] = frequency_dict[char] / length - return dict(sorted(frequency_dict.items(), key=lambda item: item[1], reverse=True)) - - -def form_key(standard, real): - res = { - key1: key2 - for (key1, _), (key2, _) in zip(standard.items(), real.items()) - if key1 in standard and key2 in real - } - return res - - -def exchange(text, key) -> str: - decrypted = "" - for char in text: - decrypted_s = key.get(char) - if decrypted_s is None: - decrypted_s = char - decrypted += decrypted_s - return decrypted - - -def main(): - try: - task2 = read_json("settings.json") - text = read_txt(task2["ENCRYPTED"]) - - if text: - freq_dict = real_frequency(text) - write_json(freq_dict, (task2["REAL_FREQ"])) - print(freq_dict) - - sample_freq = read_json(task2["STANDARD"]) - new_dict = form_key(freq_dict, sample_freq) - write_json(new_dict, (task2["KEY_DECODE"])) - print(new_dict) - - res = exchange(text, new_dict) - write_txt(res, (task2["DECRYPTED"])) - print(res) - - read = exchange(res, read_json(task2["KEY"])) - write_txt(read, (task2["TEXT"])) - print(read) - - except FileNotFoundError: - print("Ошибка: Файл не найден.") - except Exception as e: - print(f"Произошла ошибка: {e}") - -if __name__ == "__main__": - main() From d8251f6a94a27b40bbd14694cc240af69ab6523c Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:48:20 +0400 Subject: [PATCH 6/9] Delete work_files.py --- work_files.py | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 work_files.py diff --git a/work_files.py b/work_files.py deleted file mode 100644 index cff0704a..00000000 --- a/work_files.py +++ /dev/null @@ -1,40 +0,0 @@ -import json - - -def write_txt(data, filename) -> None: - try: - with open(filename, 'w', encoding='utf-8') as f: - f.write(data) - except Exception as e: - raise Exception(f"An error occurred when saving the file: {e}") - - -def read_txt(filename: str) -> str: - try: - with open(filename, 'r', encoding='utf-8') as file: - file = file.read().strip() - return file - except FileNotFoundError: - print(f"file {filename} not found") - except Exception as e: - print(f"error: {e}") - - -def read_json(filename: str) -> dict[str, str]: - try: - with open(filename, "r", encoding="utf-8") as file: - return json.load(file) - except FileNotFoundError: - print(f"file {filename} not found") - except json.JSONDecodeError: - print(f"file {filename} isn't correct JSON.") - except Exception as e: - print(f"error: {e}") - - -def write_json(dictionary, filename) -> None: - try: - with open(filename, 'w', encoding='utf-8') as file: - json.dump(dictionary, file, indent=4, ensure_ascii=False) - except Exception as e: - raise Exception(f"An error occurred when saving the file: {e}") \ No newline at end of file From f86d046514c615b04d90edf70833d52c36b7d4d5 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:26:13 +0400 Subject: [PATCH 7/9] =?UTF-8?q?6212=20=D0=9A=D1=80=D0=B8=D0=B2=D0=BE=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D0=BE=D0=B2=D0=B0=20=D0=95.=D0=A1.=20=D0=9B=D0=B0?= =?UTF-8?q?=D0=B1.3=20=D0=92=D0=B0=D1=80.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В лабораторной работе было создано приложение позволяющее генерировать ключи гибридной системы, шифровать данные гибридной системы, дешифровать данные гибридной системы. Сообщение шифруется при помощи симметричного алгоритма Camellia, а ключ симметричного алгоритма - ассиметричным алгоритмом RSA. --- lab_3/asymmetrical.py | 74 +++++++++++++++++++++++++++ lab_3/crypto_system.py | 81 +++++++++++++++++++++++++++++ lab_3/main.py | 42 ++++++++++++++++ lab_3/serialize.py | 112 +++++++++++++++++++++++++++++++++++++++++ lab_3/settings.json | 8 +++ lab_3/symmetrical.py | 75 +++++++++++++++++++++++++++ lab_3/text.txt | 1 + lab_3/work_file.py | 75 +++++++++++++++++++++++++++ 8 files changed, 468 insertions(+) create mode 100644 lab_3/asymmetrical.py create mode 100644 lab_3/crypto_system.py create mode 100644 lab_3/main.py create mode 100644 lab_3/serialize.py create mode 100644 lab_3/settings.json create mode 100644 lab_3/symmetrical.py create mode 100644 lab_3/text.txt create mode 100644 lab_3/work_file.py diff --git a/lab_3/asymmetrical.py b/lab_3/asymmetrical.py new file mode 100644 index 00000000..bf9f1fd9 --- /dev/null +++ b/lab_3/asymmetrical.py @@ -0,0 +1,74 @@ +from cryptography.hazmat.primitives import padding, hashes +from cryptography.hazmat.primitives.asymmetric import rsa, padding + + +class AsymmetricCryptography: + """ + Class for asymmetric encryption using RSA + """ + def __init__(self, private_key_path: str, public_key_path: str) -> None: + """ + Initializes AsymmetricCryptography class object + :param private_key_path: path for saving private key + :param public_key_path: path for saving public key + """ + self.private_key_path = private_key_path + self.public_key_path = public_key_path + + @staticmethod + def generate_key() -> tuple[rsa.RSAPrivateKey, rsa.RSAPublicKey]: + """ + Generates a pair of RSA keys + :return: tuple of private and public keys + """ + try: + private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) + public_key = private_key.public_key() + return private_key, public_key + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def encrypt(data: bytes, public_key: rsa.RSAPublicKey) -> bytes: + """ + Encrypts data using a public RSA key + :param data: data to encrypt + :param public_key: public key for encryption + :return: encrypted data + """ + try: + c_data = public_key.encrypt( + data, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ) + ) + return c_data + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def decrypt(data: bytes, private_key: rsa.RSAPrivateKey) -> bytes: + """ + Decrypts data using a private RSA key + :param data: encrypted data + :param private_key: private key for decryption + :return: decrypted data + """ + try: + dc_data = private_key.decrypt( + data, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ) + ) + return dc_data + except Exception as e: + print("Error:", e) + raise \ No newline at end of file diff --git a/lab_3/crypto_system.py b/lab_3/crypto_system.py new file mode 100644 index 00000000..b501fd37 --- /dev/null +++ b/lab_3/crypto_system.py @@ -0,0 +1,81 @@ +from cryptography.hazmat.primitives import padding, hashes +from cryptography.hazmat.primitives.asymmetric import padding + +from asymmetrical import AsymmetricCryptography +from serialize import Serialization +from symmetrical import SymmetricCryptography +from work_file import * + + +class HybridCryptoSystem: + """ + Class implementing a hybrid crypto system using SEED (symmetric) and RSA (asymmetric) algorithms + """ + + def __init__(self, symmetric_key_path: str, private_key_path: str, public_key_path: str) -> None: + """ + Initializes HybridCryptoSystem class object + :param symmetric_key_path: path for saving symmetrical key + :param private_key_path: path for saving private key + :param public_key_path: path for saving public key + """ + self.block_size = 128 + self.symmetric = SymmetricCryptography(symmetric_key_path) + self.asymmetric = AsymmetricCryptography(private_key_path, public_key_path) + + def generate_keys(self, size: int) -> None: + """ + Generates key for hybrid method + :param size: size of keys + """ + try: + symmetric_key = self.symmetric.generate_key(size) + asymmetric_key = self.asymmetric.generate_key() + private_key, public_key = asymmetric_key + + Serialization.save_private_key(self.asymmetric.private_key_path, private_key) + Serialization.save_public_key(self.asymmetric.public_key_path, public_key) + write_bytes(public_key.encrypt(symmetric_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ) + ), + self.symmetric.key_path) + except Exception as e: + print("Error:", e) + raise + + def encrypt(self, data_path: str, encrypted_data_path: str) -> None: + """ + Encrypts a file using a hybrid system + :param data_path: path to file with data + :param encrypted_data_path: path to file for saving encrypted data + """ + try: + text = bytes(read_txt(data_path), "UTF-8") + key = Serialization.load_private_key(self.asymmetric.private_key_path) + symmetric_key = self.asymmetric.decrypt(read_bytes(self.symmetric.key_path), key) + c_text = self.symmetric.encrypt(text, symmetric_key) + write_bytes(c_text, encrypted_data_path) + except Exception as e: + print("Error:", e) + raise + + def decrypt(self, data_path: str, decrypted_data_path: str) -> None: + """ + Decrypts a file using a hybrid system + :param data_path: path to file with data + :param decrypted_data_path: path to file for saving decrypted data + :return: + """ + try: + c_data = read_bytes(data_path) + key = Serialization.load_private_key(self.asymmetric.private_key_path) + symmetric_key = self.asymmetric.decrypt(read_bytes(self.symmetric.key_path), key) + dc_data = self.symmetric.decrypt(c_data, symmetric_key) + write_bytes(dc_data, decrypted_data_path) + except Exception as e: + print("Error:", e) + raise \ No newline at end of file diff --git a/lab_3/main.py b/lab_3/main.py new file mode 100644 index 00000000..a8ce664f --- /dev/null +++ b/lab_3/main.py @@ -0,0 +1,42 @@ +import argparse + +from crypto_system import HybridCryptoSystem +from work_file import * + + +def main(): + paths = read_json("settings.json") + + main_parser = argparse.ArgumentParser() + group = main_parser.add_mutually_exclusive_group(required=True) + group.add_argument("-gen", "--generation", help="key generation mode", nargs='?', const=32, default=None, type=int, + choices=[16, 24, 32]) + group.add_argument("-enc", "--encryption", help="encryption mode", action="store_true") + group.add_argument("-dec", "--decryption", help="decryption mode", action="store_true") + + main_parser.add_argument("--symmetric-key", help="path to symmetric key", default=paths["symmetric_key"]) + main_parser.add_argument("--secret-key", help="path to secret key", default=paths["secret_key"]) + main_parser.add_argument("--public-key", help="path to public key", default=paths["public_key"]) + + args = main_parser.parse_args() + + args.generation_flag = args.generation is not None + + if args.generation_flag and args.generation is None: + args.generation = 32 + + match (args.generation_flag, args.encryption, args.decryption): + case (True, False, False): + key_size = args.generation + h = HybridCryptoSystem(args.symmetric_key, args.secret_key, args.public_key) + h.generate_keys(key_size) + case (False, True, False): + h = HybridCryptoSystem(args.symmetric_key, args.secret_key, args.public_key) + h.encrypt(paths["initial_file"], paths["encrypted_file"]) + case (False, False, True): + h = HybridCryptoSystem(args.symmetric_key, args.secret_key, args.public_key) + h.decrypt(paths["encrypted_file"], paths["decrypted_file"]) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/lab_3/serialize.py b/lab_3/serialize.py new file mode 100644 index 00000000..550bcd91 --- /dev/null +++ b/lab_3/serialize.py @@ -0,0 +1,112 @@ +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives.serialization import ( + load_pem_public_key, + load_pem_private_key, +) + + +class Serialization: + """ + Class for serializing and deserializing cryptographic keys + """ + + @staticmethod + def save_symmetric_key(file_path: str, key: bytes) -> None: + """ + Saves the symmetric key to file + :param file_path: path to file to save + :param key: key to save + """ + try: + with open(file_path, "wb") as key_file: + key_file.write(key) + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def load_symmetric_key(file_path: str) -> bytes: + """ + Loads the symmetric key from file + :param file_path: path to file with key + :return: key + """ + try: + with open(file_path, "rb") as key_file: + return key_file.read() + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def save_private_key(path: str, private_key: rsa.RSAPrivateKey) -> None: + """ + Saves the private RSA key to a file + :param path: path to file to save + :param private_key: the RSA private key + """ + try: + with open(path, "wb") as private_out: + private_out.write( + private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + ) + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def save_public_key(path: str, public_key: rsa.RSAPublicKey) -> None: + """ + Saves the public RSA key to a file + :param path: path to file to save + :param public_key: the RSA public key + """ + try: + with open(path, "wb") as public_out: + public_out.write( + public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo, + ) + ) + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def load_private_key(path: str) -> rsa.RSAPrivateKey: + """ + Loads a private RSA key from a file + :param path: the path to the file that contains the key + :return: the RSA private key + """ + try: + with open(path, "rb") as pem_in: + private_bytes = pem_in.read() + d_private_key = load_pem_private_key( + private_bytes, + password=None, + ) + return d_private_key + except Exception as e: + print("Error:", e) + + @staticmethod + def load_public_key(path: str) -> rsa.RSAPublicKey: + """ + Loads a public RSA key from a file + :param path: the path to the file that contains the key + :return: the RSA public key + """ + try: + with open(path, "rb") as pem_in: + public_bytes = pem_in.read() + d_public_key = load_pem_public_key(public_bytes) + return d_public_key + except Exception as e: + print("Error:", e) \ No newline at end of file diff --git a/lab_3/settings.json b/lab_3/settings.json new file mode 100644 index 00000000..5a9ea02c --- /dev/null +++ b/lab_3/settings.json @@ -0,0 +1,8 @@ +{ + "symmetric_key": "symmetric_key.txt", + "public_key": "public.pem", + "secret_key": "private.pem", + "initial_file": "text.txt", + "encrypted_file": "encrypted_text.txt", + "decrypted_file": "decrypted_text.txt" +} \ No newline at end of file diff --git a/lab_3/symmetrical.py b/lab_3/symmetrical.py new file mode 100644 index 00000000..d4a88b6f --- /dev/null +++ b/lab_3/symmetrical.py @@ -0,0 +1,75 @@ +import os + +from cryptography.hazmat.primitives import padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + + +class SymmetricCryptography: + """ + class for symmetric encryption using the Camellia algorithm + """ + def __init__(self, key_path: str) -> None: + """ + initializes SymmetricCryptography class object + :param key_path: path to key + """ + self.key_path = key_path + + @staticmethod + def generate_key(size: int) -> bytes: + """ + generate key for symmetrical method + :param size: size of key + :return: generated key + """ + try: + key = os.urandom(size) + return key + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def encrypt(data: bytes, key: bytes) -> bytes: + """ + encrypts data using the Camellia algorithm in CBC mode + :param data: data to encrypt + :param key: key for encryption + :return: encrypted data in iv + ciphertext format + """ + if len(key) not in {16, 24, 32}: + raise ValueError("the size of key must be 16, 24, or 32 bytes") + try: + iv = os.urandom(16) + cipher = Cipher(algorithms.Camellia(key), modes.CBC(iv)) + encryptor = cipher.encryptor() + padder = padding.PKCS7(algorithms.Camellia.block_size).padder() + padded_text = padder.update(data) + padder.finalize() + c_text = iv + encryptor.update(padded_text) + encryptor.finalize() + return c_text + except Exception as e: + print("Error:", e) + raise + + @staticmethod + def decrypt(data: bytes, key: bytes) -> bytes: + """ + decrypts data encrypted with the encrypt method + :param data: encrypted data in iv + ciphertext format + :param key: key for decryption + :return: decrypted data + """ + if len(key) not in {16, 24, 32}: + raise ValueError("the size of key must be 16, 24, or 32 bytes") + try: + iv = data[:16] + data = data[16:] + cipher = Cipher(algorithms.Camellia(key), modes.CBC(iv)) + decryptor = cipher.decryptor() + dc_data = decryptor.update(data) + decryptor.finalize() + unpadder = padding.PKCS7(algorithms.Camellia.block_size).unpadder() + unpadded_dc_data = unpadder.update(dc_data) + unpadder.finalize() + return unpadded_dc_data + except Exception as e: + print("Error:", e) + raise \ No newline at end of file diff --git a/lab_3/text.txt b/lab_3/text.txt new file mode 100644 index 00000000..1739e78c --- /dev/null +++ b/lab_3/text.txt @@ -0,0 +1 @@ +Она несла в руках отвратительные, тревожные желтые цветы. Черт их знает, как их зовут, но они первые почему-то появляются в Москве. И эти цветы очень отчетливо выделялись на черном ее весеннем пальто. Она несла желтые цветы! Нехороший цвет. Она повернула с Тверской в переулок и тут обернулась. Ну, Тверскую вы знаете? По Тверской шли тысячи людей, но я вам ручаюсь, что увидела она меня одного и поглядела не то что тревожно, а даже как будто болезненно. И меня поразила не столько ее красота, сколько необыкновенное, никем не виданное одиночество в глазах! \ No newline at end of file diff --git a/lab_3/work_file.py b/lab_3/work_file.py new file mode 100644 index 00000000..ca111e43 --- /dev/null +++ b/lab_3/work_file.py @@ -0,0 +1,75 @@ +import json + + +def read_bytes(path: str) -> bytes: + """ + Reads bytes from txt file + :param path: path to txt file + :return: bytes + """ + try: + with open(path, "rb") as file: + data = file.read() + return data + except Exception as e: + print("Error:", e) + + +def write_bytes(data: bytes, path: str) -> None: + """ + Writes bytes into txt file + :param data: bytes object that is needed to write + :param path: path to txt file + """ + try: + with open(path, "wb") as file: + file.write(data) + except Exception as e: + print("Error:", e) + + +def read_txt(filename: str) -> str: + """ + Read and return the content of a text file + :param filename: path to the text file to be read + :return: content of the file as a string + """ + try: + with open(filename, 'r', encoding='utf-8') as file: + file = file.read().strip() + return file + except FileNotFoundError: + print(f"file {filename} not found") + except Exception as e: + print(f"error: {e}") + + +def write_txt(data: str, filename: str) -> None: + """ + Writes string into txt file + :param data: object that is needed to write + :param filename: path to the output txt file + :return: + """ + try: + with open(filename, 'w', encoding='utf-8') as f: + f.write(data) + except Exception as e: + raise Exception(f"An error occurred when saving the file: {e}") + + +def read_json(filename: str) -> dict: + """ + Read and parse a JSON file into a dictionary + :param filename: path to the text file to be read + :return: parsed JSON data as a dictionary + """ + try: + with open(filename, "r", encoding="utf-8") as file: + return json.load(file) + except FileNotFoundError: + print(f"file {filename} not found") + except json.JSONDecodeError: + print(f"file {filename} isn't correct JSON.") + except Exception as e: + print(f"error: {e}") \ No newline at end of file From e7fbac721d571245316f32f171924609668df801 Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:30:17 +0400 Subject: [PATCH 8/9] Add files via upload Add keys --- private.pem | 27 +++++++++++++++++++++++++++ public.pem | 9 +++++++++ symmetric_key.txt | Bin 0 -> 256 bytes 3 files changed, 36 insertions(+) create mode 100644 private.pem create mode 100644 public.pem create mode 100644 symmetric_key.txt diff --git a/private.pem b/private.pem new file mode 100644 index 00000000..3c30684d --- /dev/null +++ b/private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApAJlIIqbo1GPAIuukUzEwaKfQ0jyFxHDos2iPFSgNL6BSW9F +0aMyqi80Y98+6YOJSl8ssPIRq6NOCbUngy4vlUxMr7raw+JXDr0jiQIjogQZpeSM +rF4kHMB3f99bd4VOMdYVXk+GPoEwK0ula0rVRDdqhAWyPOqTibWBEApRtMkT7Fgr +B0wP0bGP4GS4vBkLX2u+ty7yHfJiZ+KaZyiStveFkc0WhWuaUv6pejV8Oqx84Byu +0iGk2IpCxDrNkTo8/Z4UVHGrrhAolNIJUd2vtgJcRLNAhiRMk2oNPcOJWu6l6ZYx +YzY+D9Exmw+vb5DKpQC7+aRjb0HsNcDnlyYZzQIDAQABAoIBABRPNZ2jfGVrfpVX +Nr1Ib974l9c5q7zelsbMxwfIhPQzGQhybodouafoY4jwhrZc8v3SLlMVDsod1VaP +Z76vU/YddiuWrGtwVk59bm6TZL0128U2uZLIr5kd3k5n5sg0qjuyon/Ewj9wOPpL +ikbwg9tIL3j8yZcQh0eYwcwuMvL7dpYfBaK+rGKrqcN2R2tGHTkTsct3DYhuZycY +v25IkE09PmWeKhlIEikHoXI8AiAjJjK+tyZyN8dGcerWTNpvwa0dRZN3KAgruH62 +/tgmN93EFZ4vDO/pknsRTZATmwRvYmPUK3I8giKgCsn5WxJH9ugI69gb9RoJeQbk +sv43mvMCgYEA2S5zBBBr06uc6xZ2O1wYjnjcJlrcV4CkJ99U7tlaL0DyrbQPJuy0 +1zl8BT1uBCvfj/auKOYe5qSoXC4XQUasnhqCQIWtlEnWf4MEm1lhAfiVK2Wur3Oy +XvE0IwwVi+ud3R6CHWWkKktx6lh2NezlB0uGHD+ng4awN27Z831Ye3cCgYEAwVL0 +oeqsl6YSO41ZUbc0sbtU6RgMm0sOHJT0HDrsSkNbXZ6agSkiqYOJyYL3oE3ZdC2m +TBh6Gb7IK4i1tCv/srOCc57r2nf20/jh7oKeZjqY0hpQ+sdykAFC4CKYlYKLiqjV +vMHHgINGPBO8SFwTNSWH0DmvvdMh3OPeZItIHdsCgYAYUTUbnWMVXj/BqtAuMU+m +lC3CNaY6PfMja8QswjVw2QrTHDgeGZ7eAle6lng9C1SK4An8FlgbZxBa0eZUrr8h +LMKsysr2sZXMzTS02DseZ2D8bPQ0PPYZ31QBIJdBBW61lXboJ7tL6QqmPKVvwEic +mn43p4DwHyKX8leBBeXkXQKBgFrgOvzOCtmyiEmUNVNzUoLls5Fq66ooSvbmkiWf +ESoLpaxJfQmQI6oZmjCuruadEcZKGy0UKHlntEK6neeW8zi2p3DgWLA2ykF0cggj +QIB/tQy2sDBihxjobt5bhOxrFFtW6Do1wSlJDD/7avt8xM6r2L7qDxGlaPqj5wvO +aVUXAoGAMFAsOK3P5iwahix65VFBkHYf83MLi/k912+1kTSVT149NbMwsek3MubO +qQvfGUfmueHlUl7i0bD8QPgQ3yqrlrVKZGRgT3IQN7sXM5v73UmWyO7Nctpf1U14 +89Z+EEPBSqJP1Ge+EFhNm8iy8NPv7VYuP3YbTtxCwTzq/He3rHw= +-----END RSA PRIVATE KEY----- diff --git a/public.pem b/public.pem new file mode 100644 index 00000000..fbc47dbc --- /dev/null +++ b/public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApAJlIIqbo1GPAIuukUzE +waKfQ0jyFxHDos2iPFSgNL6BSW9F0aMyqi80Y98+6YOJSl8ssPIRq6NOCbUngy4v +lUxMr7raw+JXDr0jiQIjogQZpeSMrF4kHMB3f99bd4VOMdYVXk+GPoEwK0ula0rV +RDdqhAWyPOqTibWBEApRtMkT7FgrB0wP0bGP4GS4vBkLX2u+ty7yHfJiZ+KaZyiS +tveFkc0WhWuaUv6pejV8Oqx84Byu0iGk2IpCxDrNkTo8/Z4UVHGrrhAolNIJUd2v +tgJcRLNAhiRMk2oNPcOJWu6l6ZYxYzY+D9Exmw+vb5DKpQC7+aRjb0HsNcDnlyYZ +zQIDAQAB +-----END PUBLIC KEY----- diff --git a/symmetric_key.txt b/symmetric_key.txt new file mode 100644 index 0000000000000000000000000000000000000000..f129fc1227d076aa350cdc189ed6a380173a1572 GIT binary patch literal 256 zcmV+b0ssCZuQ6d>gcAY2bd0?8*233r&OkOXc0cNW*u6rz*JN~`$1)ty5#BWJ<^{{D zA6sY_zwO`dmm+&5mkZDE5;VpY7LN$ZmS=oq><7edOSkF+YO%TiVkH^? zQnLF`)!aqn2pe1{(!u#5#gX_Lck&tg3Qj&5e$JIbJQm>P6)vo^-eldf-xUZd3c~Br Gcy`OpGJ#hB literal 0 HcmV?d00001 From 28a9f4b3de4d15f1ca2e47445e3c99de5bd0471c Mon Sep 17 00:00:00 2001 From: https-katice <164325850+https-katice@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:33:32 +0400 Subject: [PATCH 9/9] Add files via upload Add encrypted text and decrypted text --- decrypted_text.txt | 1 + encrypted_text.txt | Bin 0 -> 1024 bytes 2 files changed, 1 insertion(+) create mode 100644 decrypted_text.txt create mode 100644 encrypted_text.txt diff --git a/decrypted_text.txt b/decrypted_text.txt new file mode 100644 index 00000000..1739e78c --- /dev/null +++ b/decrypted_text.txt @@ -0,0 +1 @@ +Она несла в руках отвратительные, тревожные желтые цветы. Черт их знает, как их зовут, но они первые почему-то появляются в Москве. И эти цветы очень отчетливо выделялись на черном ее весеннем пальто. Она несла желтые цветы! Нехороший цвет. Она повернула с Тверской в переулок и тут обернулась. Ну, Тверскую вы знаете? По Тверской шли тысячи людей, но я вам ручаюсь, что увидела она меня одного и поглядела не то что тревожно, а даже как будто болезненно. И меня поразила не столько ее красота, сколько необыкновенное, никем не виданное одиночество в глазах! \ No newline at end of file diff --git a/encrypted_text.txt b/encrypted_text.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ec96a8e1d28ade98f8143d7b503b0debf841dda GIT binary patch literal 1024 zcmV+b1poU{YH^~FhJh|yA0CIW=9zdTGRm&?at@S`K{0EPfj&`IMnG$?HHBpH!`<3P z%v9JsApHfAFHR2lqGsAmjKHW|7pTxrb$o%*zr7OP;I_Evz@>mmfW?IU#`;BMf1q!C zj^#eChB)tcZ0%1uj30E?X;COs!1|{@KDP@^8w&7ypLMyIf4)5M0doLN7}IO7I-*il z@G~gzqcBdAp+^~p<@2)bEB8w>DSo~$7gx*5$PQ))aeSTzvw<5=#a)idceREio5u>x zh(TFaV(lH5(u4{TN6v$0XcS2h?LKkL=0k9TCG|yJujZ*83VYpaO5@T`H1m*fi#*`R z#YHmcLCf3XM>Mp-D*tfo-oaIBVITe08ee<~#*tk&9vU`9MASCOz1q6-TN_zLOH1J` z&6aCif*2kINzX=MZq<4Ad#J4EkA^k545$7KyqbEL9ks}kq~ol&AFE`a#x*4$lZ9Eh zB^|0FW#PSA3J~`uf(H^5s37fX?r>V6OHGYh+Yk3Tff2KS6PGdV6*SzdbrV3g4+4!; zSW7%l%3MM^Qz*OO(L#o;hE&}TJSc$Mrq1;BC(HuvIGcmPmjEAN!ZzOogH&8%U$@Ui z@-P-KE32r`lLE{Lmoak2GOpku)!#-n4CA0zO0_HTY=7Q_6&=FQ#6;nMQ$Etv<%N)iObl zewchNBR@E!9C4TfV@k6qNzzu+_!L`lEZI;6dT6-U&!hBQk#9tqv|oaKBg~)EbP}Nb zp4qD}yQ)>|8EQL`3hvfbXsItpl;_=Jg{%`%`#tild=`CMqDyS*x})yFj))!u=@3zJ z7KZ8IDJ}RQQe!i6CK;%(o|2XLt*NPL(5O-I3|0*4UP=UP@M6xPp{hSxl5R^Fr7l}w zWA-;`E9#ZiFe+*S4HzeQo-G$~t)+$A`l}_~lx)kPZ>ybIqqLnKNJM;Mmu^&Er{FYH zLZs+>`anJcXesxY4UlK%{x*A7A);)H1iLco&&7N#AEW2~?Dwwtl`8{}#k(=qVr>75 z9BwV>Tw;$ww|a!lLZGYjvoU_r%Sip^s_}v%76DU8&GnazJC@W+@t9~M7xM8A?>l5| zkV6LUc@ZSd8qmPw4OqgyJ}U=Dkm%P++ei=WK1P<0s??m@d%N=#q=kXx@rwzxVAM@{ zrIOIqYYD|d6(%V40()R|k$j6