diff --git a/app.py b/app.py new file mode 100644 index 000000000..1f8587bc4 --- /dev/null +++ b/app.py @@ -0,0 +1,109 @@ +from serialize import * +from asymmetric_alg import AsymCipherManager +from symmetric_alg import SymCipherManager +from file_work import * + + +class HybridCryptosystem: + def __init__(self): + self._initialize_settings() + + def _initialize_settings(self) -> None: + """Инициализация настроек приложения""" + try: + self._settings = read_json_file("settings.json") + self._is_running = True + except Exception as e: + print("Ошибка: Не удалось загрузить файл настроек (settings.json)") + self._is_running = False + + def _display_menu(self) -> None: + """Отображение меню приложения""" + menu_items = [ + "\nВыберите действие:", + "1 - Сгенерировать ключи", + "2 - Зашифровать текст симметричным ключом", + "3 - Расшифровать текст", + "4 - Выход\n" + ] + print("\n".join(menu_items)) + + def _handle_key_generation(self) -> None: + """Обработка генерации ключей""" + try: + # Генерация ключей + private_key, public_key = AsymCipherManager.generate_rsa_keys() + symmetric_key = SymCipherManager.generate_sm4_key() + + # Сохранение ключей + serialize_public_key(self._settings["public_key"], public_key) + serialize_private_key(self._settings["private_key"], private_key) + + # Шифрование и сохранение симметричного ключа + encrypted_key = AsymCipherManager.encrypt_key(symmetric_key, public_key) + serialize_sym_key(self._settings["encrypt_sym_key"], encrypted_key) + + print("\n[Успех] Ключи сгенерированы и сохранены") + except Exception as e: + print(f"\n[Ошибка] Генерация ключей: {e}") + + def _handle_encryption(self) -> None: + """Обработка шифрования текста""" + try: + # Получение ключей + encrypted_key = deserialize_sym_key(self._settings["encrypt_sym_key"]) + private_key = deserialize_private_key(self._settings["private_key"]) + symmetric_key = AsymCipherManager.decrypt_key(encrypted_key, private_key) + + # Шифрование текста + text = read_bin_file(self._settings["text"]) + encrypted_text = SymCipherManager.encrypt_sm4(text, symmetric_key) + write_bytes_file(self._settings["encrypt_text"], encrypted_text) + + print("\n[Успех] Текст зашифрован") + except Exception as e: + print(f"\n[Ошибка] Шифрование текста: {e}") + + def _handle_decryption(self) -> None: + """Обработка дешифрования текста""" + try: + # Получение ключей + encrypted_key = deserialize_sym_key(self._settings["encrypt_sym_key"]) + private_key = deserialize_private_key(self._settings["private_key"]) + symmetric_key = AsymCipherManager.decrypt_key(encrypted_key, private_key) + + # Дешифрование текста + encrypted_text = read_bin_file(self._settings["encrypt_text"]) + decrypted_text = SymCipherManager.decrypt_sm4(encrypted_text, symmetric_key) + write_txt_file(decrypted_text.decode("UTF-8"), self._settings["decrypt_text"]) + + print("\n[Успех] Текст расшифрован") + except Exception as e: + print(f"\n[Ошибка] Дешифрование текста: {e}") + + def console_app(self) -> None: + """Основной цикл работы приложения""" + if not self._is_running: + return + + while self._is_running: + self._display_menu() + user_choice = input("Ваш выбор: ").strip() + + match user_choice: + case "1": + self._handle_key_generation() + case "2": + self._handle_encryption() + case "3": + self._handle_decryption() + case "4": + self._is_running = False + print("\nЗавершение работы программы...") + case _: + print("\n[Ошибка] Неверный ввод. Выберите пункт 1-4") + + +if __name__ == "__main__": + app = HybridCryptosystem() + app.console_app() \ No newline at end of file diff --git a/asymmetric_alg.py b/asymmetric_alg.py new file mode 100644 index 000000000..23317bd5d --- /dev/null +++ b/asymmetric_alg.py @@ -0,0 +1,85 @@ +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import padding, rsa +from cryptography.hazmat.backends import default_backend + + +class AsymCipherManager: + """Класс для асимметричного шифрования с использованием RSA""" + + @staticmethod + def generate_rsa_keys() -> tuple[rsa.RSAPrivateKey, rsa.RSAPublicKey]: + """ + Генерирует пару закрытый RSA ключ и открытый RSA ключ + :return: Кортеж (закрытый ключ, открытый ключ) + :raises RuntimeError: Если не удалось сгенерировать ключи + """ + try: + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + backend=default_backend() + ) + public_key = private_key.public_key() + return private_key, public_key + except Exception as e: + raise RuntimeError("Ошибка генерации RSA ключей") from e + + @staticmethod + def encrypt_key(sym_key: bytes, public_key: rsa.RSAPublicKey) -> bytes: + """ + Шифрует симметричный ключ с помощью открытого + :param sym_key: Симметричный ключ для шифрования + :param public_key: Открытый RSA ключ + :return: Зашифрованный симметричный ключ + :raises TypeError: Если неверный тип аргументов + :raises ValueError: Если ключ пустой или слишком большой + :raises RuntimeError: Если ошибка шифрования + """ + if not isinstance(sym_key, bytes): + raise TypeError("Симметричный ключ должен быть в формате bytes") + if not isinstance(public_key, rsa.RSAPublicKey): + raise TypeError("Открытый ключ должен быть типа RSAPublicKey") + if not sym_key: + raise ValueError("Симметричный ключ не может быть пустым") + + try: + return public_key.encrypt( + sym_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + except Exception as e: + raise RuntimeError("Ошибка шифрования ключа") from e + + @staticmethod + def decrypt_key(encr_key: bytes, private_key: rsa.RSAPrivateKey) -> bytes: + """ + Расшифровывает симметричный ключ с помощью закрытого + :param encr_key: Зашифрованный симметричный ключ + :param private_key: Закрытый RSA ключ + :return: Расшифрованный симметричный ключ + :raises TypeError: Если неверный тип аргументов + :raises ValueError: Если зашифрованный ключ пустой + :raises RuntimeError: Если ошибка дешифрования + """ + if not isinstance(encr_key, bytes): + raise TypeError("Зашифрованный ключ должен быть в формате bytes") + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError("Закрытый ключ должен быть типа RSAPrivateKey") + if not encr_key: + raise ValueError("Зашифрованный ключ не может быть пустым") + + try: + return private_key.decrypt( + encr_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + except Exception as e: + raise RuntimeError("Ошибка дешифрования ключа") from e \ No newline at end of file diff --git a/decrypt_text.txt b/decrypt_text.txt new file mode 100644 index 000000000..e74b9b5d3 --- /dev/null +++ b/decrypt_text.txt @@ -0,0 +1 @@ +Криптография — это наука о методах обеспечения конфиденциальности, целостности и аутентичности информации путем преобразования данных в форму, недоступную для понимания посторонними. Её история уходит корнями в древность: первые криптографические методы использовались ещё в Древнем Египте и Месопотамии, где применялись простые шифры для защиты важных сообщений. В эпоху античности известным примером стал шифр Цезаря, основанный на сдвиге букв алфавита на фиксированное число позиций. Средневековье принесло более сложные методы, такие как полиалфавитные шифры, предложенные Леоном Баттистой Альберти, которые значительно повысили стойкость шифрования. С развитием технологий криптография перешла от ручных методов к машинным, особенно во время Второй мировой войны, когда немецкая шифровальная машина "Энигма" и её взлом британскими специалистами, включая Алана Тьюринга, стали поворотным моментом в истории криптоанализа. Современная криптография опирается на сложные математические алгоритмы, такие как RSA, основанный на проблеме факторизации больших чисел, и ECC, использующий свойства эллиптических кривых. Симметричные шифры, например AES, обеспечивают высокую скорость шифрования, а асимметричные — безопасный обмен ключами. Криптография также лежит в основе цифровых подписей, хеш-функций и протоколов защиты данных в интернете, таких как TLS. С появлением квантовых компьютеров возникли новые вызовы, поскольку они потенциально способны взломать многие современные алгоритмы, что стимулирует развитие постквантовой криптографии. Таким образом, криптография остаётся динамичной и критически важной областью. \ No newline at end of file diff --git a/encrypt_sym_key.txt b/encrypt_sym_key.txt new file mode 100644 index 000000000..9cfc67d1f Binary files /dev/null and b/encrypt_sym_key.txt differ diff --git a/encrypt_text.txt b/encrypt_text.txt new file mode 100644 index 000000000..553853064 Binary files /dev/null and b/encrypt_text.txt differ diff --git a/file_work.py b/file_work.py new file mode 100644 index 000000000..bb5366f74 --- /dev/null +++ b/file_work.py @@ -0,0 +1,98 @@ +import json + +def read_json_file(file_path: str) -> dict: + """ + Читает данные из JSON файла + :param file_path: Путь к JSON файлу + :return: Словарь с данными из файла + :raises FileNotFoundError: Если файл не существует + :raises PermissionError: Если нет прав на чтение файла + :raises Exception: При других ошибках чтения + """ + try: + with open(file_path, 'r', encoding='utf-8') as file: + return json.load(file) + except FileNotFoundError as e: + raise FileNotFoundError(f"Файл не найден: {file_path}") from e + except PermissionError as e: + raise PermissionError(f"Нет прав на чтение файла: {file_path}") from e + except Exception as e: + raise Exception(f"Ошибка при чтении JSON файла: {file_path}") from e + +def write_json_file(file_path: str, data: dict) -> None: + """ + Записывает данные в JSON файл + :param file_path: Путь к файлу для записи + :param data: Данные для записи (словарь) + :raises TypeError: Если данные не сериализуемы в JSON + :raises PermissionError: Если нет прав на запись + :raises Exception: При других ошибках записи + """ + try: + with open(file_path, 'w', encoding='utf-8') as file: + json.dump(data, file, ensure_ascii=False, indent=4) + except TypeError as e: + raise TypeError(f"Ошибка сериализации данных в JSON: {e}") from e + except PermissionError as e: + raise PermissionError(f"Нет прав на запись в файл: {file_path}") from e + except Exception as e: + raise Exception(f"Ошибка при записи JSON файла: {file_path}") from e + +def read_bin_file(file_path: str) -> bytes: + """ + Читает содержимое бинарного файла + :param file_path: Путь к бинарному файлу + :return: Байтовая строка с содержимым файла + :raises FileNotFoundError: Если файл не существует + :raises PermissionError: Если нет прав на чтение + :raises Exception: При других ошибках чтения + """ + try: + with open(file_path, 'rb') as file: + return file.read() + except FileNotFoundError as e: + raise FileNotFoundError(f"Файл не найден: {file_path}") from e + except PermissionError as e: + raise PermissionError(f"Нет прав на чтение файла: {file_path}") from e + except Exception as e: + raise Exception(f"Ошибка при чтении бинарного файла: {file_path}") from e + +def write_txt_file(data: str, file_path: str) -> None: + """ + Сохраняет текстовые данные в файл + :param data: Текст который нужно записать в файл + :param file_path: Путь к файлу + :return: None + :raises FileNotFoundError: Если не удалось найти или создать файл по указанному пути + :raises PermissionError: Если нет прав на запись в файл + :raises Exception: При других ошибках записи + """ + try: + with open(file_path, 'w', encoding='utf-8') as file: + file.write(data) + except FileNotFoundError as e: + raise FileNotFoundError(f"Файл не найден: {file_path}") from e + except PermissionError as e: + raise PermissionError(f"Нет прав на запись в файл: {file_path}") from e + except Exception as e: + raise Exception(f"Ошибка при записи файла ммм: {file_path}") from e + +def write_bytes_file(file_path: str, data: bytes) -> None: + """ + Сохраняет бинарные данные в файл + :param file_path: Путь к файлу + :param data: Бинарные данные, которые нужно записать + :return: None + :raises FileNotFoundError: Если не удалось найти или создать файл по указанному пути + :raises PermissionError: Если нет прав на запись в файл + :raises Exception: При других ошибках записи + """ + try: + with open(file_path, 'wb') as file: + file.write(data) + except FileNotFoundError as e: + raise FileNotFoundError(f"Файл не найден: {file_path}") from e + except PermissionError as e: + raise PermissionError(f"Нет прав на запись в файл: {file_path}") from e + except Exception as e: + raise Exception(f"Ошибка при записи файла: {file_path}") from e \ No newline at end of file diff --git a/private_key.pem b/private_key.pem new file mode 100644 index 000000000..138db6cc2 --- /dev/null +++ b/private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAxPajp2C5jFicPJlb1YtwDoZ6lHVPzLGjnZNg/Rvd3hZHkAyq +Ug0ews/j8L1QD6vWz1rOBaLfB+ksQFuF2aXMoIuy87G7xKFlJUdaxScqQ7dm5Js7 +cMYD5NuS0GgHBxQ6gstHX3GfkVUK4bec1vcLDDUasm3Gr1PGI0DOpc81HK5QTo+Y +9Tah2tF6CpXnraM+WeoGqJ5ZVSBFPTgdUyJaiK/vrmfx5UE7f6CYhBEOXPdtJW2T +NftnRZwa8FH+DIGl3a3ImaAowlBCNUQhVWFH4JMNP9sFcTeKvfUUinsUmtY1teBI +d7/1jb73uRUn2LV5/7F5gvLLKU5k77dgB33bOwIDAQABAoIBAEsrpkHXFHmPx/EI +xpe1Y8rnYBkQvKfuk/crrDRtUjvUXPOJIee2wiqvlNroJYoVlyIEEeTsyBoIz66w +P2FVecc8Ccwf5P2iayvTE71yuRqnAEn3RLRBnnLVqi6HxUbaXYpVcqPmhXO99S04 +Gk+gcULzcYDvjIiVfGUv8q4taqPK51Saky4RsHv60KkIVTiVygx9M5jZJURquNXj +w7SOtMIyCmlScXmq3Q9YKv0cSh0UBQgRIbbA82KkMqMOf3+4Jjs6X3qIPjiHEbXs +p9DQa59rjmUSM23k9sDx7mpYoByG0zJHeCB6hG5ZRZ1Ozkc9xuuOAlakLZuL+37a ++x/GncECgYEA8c2diPzZ3hBdbbruPYov2Ep8eSaflLjhu7fnsVce1VXJfknjNMql +JPns7RVjmdkYO3PkCjDs1mi7B8TZ7R/JYuPVw7fDyNUt6SJ2MnhnYI2I9t+K8NZj +s5JjvXAxiHk6//ZK8okb9OYFOK6RxAtwWXFN707SRgO+UzmWQ8e86rMCgYEA0IcR +LeQWhqZZ4XK7DBluNpZLCgcAtiRz85dH49BDyH7bV4ZeD/dQz8uyf9vU+HOtt3Ha +VVAyM/ksWeGkVmC1Ftk/xnBghb9PCCpHq/4YMetYjS2+0aqV5CD1CVqnxFSg/EG/ +EfjES5Ew4g9CDaRzsfZzHmapoHTuCX6MRZyMMVkCgYA+3dWaexrt2FViJRqx106v +LlaEbR1KXnMaCitr+RmkH6S+d9lhrVoYbf5CebAmnMHnGy9r0uKQsDQIRg7ezsfe +NRwrwYhem8ZO+c2/O3ytJr84aFBIY4USd/oEk7ndIJ/NUqyTuEATgQZUgVaWoN65 +8nJvyI908p42Jx/BSZn9bwKBgQDKWtfL7bQCVHmSMpDay+7M4AnPoD4LgtJWhu6H +Xzn33Uqi48xxt/DexO/h7YT82Nyx0LUr5tfg4aMtUa7094Gju4yM186C28Qoy0aj +277E6noS/lpXAi/UojrHKgb1mZ5jTLXLDdoG7s0+Acp6jKSNBPhvfvaKtA2ufvRG +NQVCeQKBgQCMMPqy0RCpfW2uzgxahOq2f9QFieivEfhOIhm2J09uw9XbluCh3bw4 +MTbiApjuhOHkOffXBeIkCoRgqnwj/+wuXYIiYtx5XpeX/pPTlqw7n5g7bQ2zKfw8 +Ew/8dZD2zG1voWcoM3OoWzuVozqJScagbp1N5XYiIiqu2FfQBx25vg== +-----END RSA PRIVATE KEY----- diff --git a/public_key.pem b/public_key.pem new file mode 100644 index 000000000..8ca4666b6 --- /dev/null +++ b/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxPajp2C5jFicPJlb1Ytw +DoZ6lHVPzLGjnZNg/Rvd3hZHkAyqUg0ews/j8L1QD6vWz1rOBaLfB+ksQFuF2aXM +oIuy87G7xKFlJUdaxScqQ7dm5Js7cMYD5NuS0GgHBxQ6gstHX3GfkVUK4bec1vcL +DDUasm3Gr1PGI0DOpc81HK5QTo+Y9Tah2tF6CpXnraM+WeoGqJ5ZVSBFPTgdUyJa +iK/vrmfx5UE7f6CYhBEOXPdtJW2TNftnRZwa8FH+DIGl3a3ImaAowlBCNUQhVWFH +4JMNP9sFcTeKvfUUinsUmtY1teBId7/1jb73uRUn2LV5/7F5gvLLKU5k77dgB33b +OwIDAQAB +-----END PUBLIC KEY----- diff --git a/serialize.py b/serialize.py new file mode 100644 index 000000000..cbd898901 --- /dev/null +++ b/serialize.py @@ -0,0 +1,128 @@ +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.serialization import ( + load_pem_public_key, + load_pem_private_key, +) + + +def serialize_public_key(path: str, public_key: rsa.RSAPublicKey) -> None: + """ + Сериализует открытый RSA-ключ в файл. + :param path: Путь к файлу для сохранения + :param public_key: Открытый RSA-ключ + :raises ValueError: Если ключ недействителен + :raises IOError: Если произошла ошибка записи + """ + if not isinstance(public_key, rsa.RSAPublicKey): + raise ValueError("Неверный тип открытого ключа") + + try: + pem = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + with open(path, 'wb') as f: + f.write(pem) + except IOError as e: + raise IOError(f"Ошибка записи открытого ключа: {e}") + except Exception as e: + raise ValueError(f"Ошибка сериализации открытого ключа: {e}") + + +def serialize_private_key(path: str, private_key: rsa.RSAPrivateKey) -> None: + """ + Сериализует закрытый RSA-ключ в файл. + :param path: Путь к файлу для сохранения + :param private_key: Закрытый RSA-ключ + :raises ValueError: Если ключ недействителен + :raises IOError: Если произошла ошибка записи + """ + if not isinstance(private_key, rsa.RSAPrivateKey): + raise ValueError("Неверный тип закрытого ключа") + + try: + pem = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption() + ) + with open(path, 'wb') as f: + f.write(pem) + except IOError as e: + raise IOError(f"Ошибка записи закрытого ключа: {e}") + except Exception as e: + raise ValueError(f"Ошибка сериализации закрытого ключа: {e}") + + +def serialize_sym_key(path: str, sym_key: bytes) -> None: + """ + Сериализует симметричный ключ в файл. + :param path: Путь к файлу для сохранения + :param sym_key: Симметричный ключ + :raises ValueError: Если ключ пустой + :raises IOError: Если произошла ошибка записи + """ + if not sym_key: + raise ValueError("Симметричный ключ не может быть пустым") + + try: + with open(path, 'wb') as f: + f.write(sym_key) + except IOError as e: + raise IOError(f"Ошибка записи симметричного ключа: {e}") + + +def deserialize_public_key(path: str) -> rsa.RSAPublicKey: + """ + Десериализует открытый RSA-ключ из файла. + :param path: Путь к файлу с ключом + :return: Открытый RSA-ключ + :raises IOError: Если произошла ошибка чтения + :raises ValueError: Если файл поврежден + """ + try: + with open(path, 'rb') as f: + pem = f.read() + return load_pem_public_key(pem, backend=default_backend()) + except IOError as e: + raise IOError(f"Ошибка чтения открытого ключа: {e}") + except Exception as e: + raise ValueError(f"Ошибка десериализации открытого ключа: {e}") + + +def deserialize_private_key(path: str) -> rsa.RSAPrivateKey: + """ + Десериализует закрытый RSA-ключ из файла. + :param path: Путь к файлу с ключом + :return: Закрытый RSA-ключ + :raises IOError: Если произошла ошибка чтения + :raises ValueError: Если файл поврежден + """ + try: + with open(path, 'rb') as f: + pem = f.read() + return load_pem_private_key(pem, password=None, backend=default_backend()) + except IOError as e: + raise IOError(f"Ошибка чтения закрытого ключа: {e}") + except Exception as e: + raise ValueError(f"Ошибка десериализации закрытого ключа: {e}") + + +def deserialize_sym_key(path: str) -> bytes: + """ + Десериализует симметричный ключ из файла. + :param path: Путь к файлу с ключом + :return: Симметричный ключ + :raises IOError: Если произошла ошибка чтения + :raises ValueError: Если файл пустой + """ + try: + with open(path, 'rb') as f: + key = f.read() + if not key: + raise ValueError("Файл с симметричным ключом пуст") + return key + except IOError as e: + raise IOError(f"Ошибка чтения симметричного ключа: {e}") \ No newline at end of file diff --git a/settings.json b/settings.json new file mode 100644 index 000000000..65b5a80bd --- /dev/null +++ b/settings.json @@ -0,0 +1,8 @@ +{ + "text": "text.txt", + "encrypt_text": "encrypt_text.txt", + "decrypt_text": "decrypt_text.txt", + "encrypt_sym_key": "encrypt_sym_key.txt", + "private_key": "private_key.pem", + "public_key": "public_key.pem" +} \ No newline at end of file diff --git a/symmetric_alg.py b/symmetric_alg.py new file mode 100644 index 000000000..30d82d156 --- /dev/null +++ b/symmetric_alg.py @@ -0,0 +1,108 @@ +from cryptography.hazmat.primitives import padding as symmetric_padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +import os + + +class SymCipherManager: + """Класс для симметричного шифрования с использованием алгоритма SM4""" + + @staticmethod + def generate_sm4_key() -> bytes: + """ + Генерирует ключ алгоритма шифрования SM4 + :return: 16-байтный ключ + :raises RuntimeError: Если не удалось сгенерировать ключ + """ + try: + return os.urandom(16) + except Exception as e: + raise RuntimeError("Ошибка генерации ключа") from e + + @staticmethod + def apply_padding(data: bytes) -> bytes: + """ + Добавляет PKCS7 паддинг к данным + :param data: Данные для паддинга + :return: Данные с паддингом + :raises TypeError: Если данные не в формате bytes + """ + if not isinstance(data, bytes): + raise TypeError("Данные должны быть в формате bytes") + + padder = symmetric_padding.PKCS7(128).padder() + return padder.update(data) + padder.finalize() + + @staticmethod + def remove_padding(data: bytes) -> bytes: + """ + Удаляет PKCS7 паддинг из данных + :param data: данные с паддингом + :return: данные без паддинга + :raises TypeError: Если данные не в формате bytes + """ + if not isinstance(data, bytes): + raise TypeError("Данные должны быть в формате bytes") + + unpadder = symmetric_padding.PKCS7(128).unpadder() + try: + return unpadder.update(data) + unpadder.finalize() + except Exception as e: + raise RuntimeError("Ошибка удаления паддинга") from e + + @staticmethod + def encrypt_sm4(text: bytes, key: bytes) -> bytes: + """ + Шифрует текст с помощью алгоритма SM4 + :param text: Текст для шифрования + :param key: Ключ шифрования (16 байт) + :return: iv + зашифрованный текст + :raises TypeError: Если неверный тип данных + :raises ValueError: Если неверная длина ключа или данных + :raises RuntimeError: Если ошибка шифрования + """ + if not isinstance(text, bytes) or not isinstance(key, bytes): + raise TypeError("Данные и ключ должны быть в формате bytes") + if len(key) != 16: + raise ValueError("Ключ должен быть длиной 16 байт") + if not text: + raise ValueError("Текст для шифрования не может быть пустым") + + try: + iv = os.urandom(16) + padded_data = SymCipherManager.apply_padding(text) + cipher = Cipher(algorithms.SM4(key), modes.CBC(iv)) + encryptor = cipher.encryptor() + ciphertext = encryptor.update(padded_data) + encryptor.finalize() + + return iv + ciphertext + except Exception as e: + raise RuntimeError("Ошибка шифрования") from e + + @staticmethod + def decrypt_sm4(ciphertext: bytes, key: bytes) -> bytes: + """ + Расшифровывает текст с помощью алгоритма SM4 + :param ciphertext: iv + зашифрованный текст + :param key: Ключ расшифровки + :return: Расшифрованный текст + :raises TypeError: Если неверный тип данных + :raises ValueError: Если неверная длина ключа или данных + :raises RuntimeError: Если ошибка дешифрования + """ + if not isinstance(ciphertext, bytes) or not isinstance(key, bytes): + raise TypeError("Данные и ключ должны быть в формате bytes") + if len(key) != 16: + raise ValueError("Ключ должен быть 16 байт") + if len(ciphertext) < 16: + raise ValueError("Шифротекст короткий") + + try: + iv = ciphertext[:16] + encrypted_data = ciphertext[16:] + cipher = Cipher(algorithms.SM4(key), modes.CBC(iv)) + decryptor = cipher.decryptor() + padded_text = decryptor.update(encrypted_data) + decryptor.finalize() + + return SymCipherManager.remove_padding(padded_text) + except Exception as e: + raise RuntimeError("Ошибка дешифрования") from e \ No newline at end of file diff --git a/text.txt b/text.txt new file mode 100644 index 000000000..e74b9b5d3 --- /dev/null +++ b/text.txt @@ -0,0 +1 @@ +Криптография — это наука о методах обеспечения конфиденциальности, целостности и аутентичности информации путем преобразования данных в форму, недоступную для понимания посторонними. Её история уходит корнями в древность: первые криптографические методы использовались ещё в Древнем Египте и Месопотамии, где применялись простые шифры для защиты важных сообщений. В эпоху античности известным примером стал шифр Цезаря, основанный на сдвиге букв алфавита на фиксированное число позиций. Средневековье принесло более сложные методы, такие как полиалфавитные шифры, предложенные Леоном Баттистой Альберти, которые значительно повысили стойкость шифрования. С развитием технологий криптография перешла от ручных методов к машинным, особенно во время Второй мировой войны, когда немецкая шифровальная машина "Энигма" и её взлом британскими специалистами, включая Алана Тьюринга, стали поворотным моментом в истории криптоанализа. Современная криптография опирается на сложные математические алгоритмы, такие как RSA, основанный на проблеме факторизации больших чисел, и ECC, использующий свойства эллиптических кривых. Симметричные шифры, например AES, обеспечивают высокую скорость шифрования, а асимметричные — безопасный обмен ключами. Криптография также лежит в основе цифровых подписей, хеш-функций и протоколов защиты данных в интернете, таких как TLS. С появлением квантовых компьютеров возникли новые вызовы, поскольку они потенциально способны взломать многие современные алгоритмы, что стимулирует развитие постквантовой криптографии. Таким образом, криптография остаётся динамичной и критически важной областью. \ No newline at end of file