Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -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()
85 changes: 85 additions & 0 deletions asymmetric_alg.py
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions decrypt_text.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Криптография — это наука о методах обеспечения конфиденциальности, целостности и аутентичности информации путем преобразования данных в форму, недоступную для понимания посторонними. Её история уходит корнями в древность: первые криптографические методы использовались ещё в Древнем Египте и Месопотамии, где применялись простые шифры для защиты важных сообщений. В эпоху античности известным примером стал шифр Цезаря, основанный на сдвиге букв алфавита на фиксированное число позиций. Средневековье принесло более сложные методы, такие как полиалфавитные шифры, предложенные Леоном Баттистой Альберти, которые значительно повысили стойкость шифрования. С развитием технологий криптография перешла от ручных методов к машинным, особенно во время Второй мировой войны, когда немецкая шифровальная машина "Энигма" и её взлом британскими специалистами, включая Алана Тьюринга, стали поворотным моментом в истории криптоанализа. Современная криптография опирается на сложные математические алгоритмы, такие как RSA, основанный на проблеме факторизации больших чисел, и ECC, использующий свойства эллиптических кривых. Симметричные шифры, например AES, обеспечивают высокую скорость шифрования, а асимметричные — безопасный обмен ключами. Криптография также лежит в основе цифровых подписей, хеш-функций и протоколов защиты данных в интернете, таких как TLS. С появлением квантовых компьютеров возникли новые вызовы, поскольку они потенциально способны взломать многие современные алгоритмы, что стимулирует развитие постквантовой криптографии. Таким образом, криптография остаётся динамичной и критически важной областью.
Binary file added encrypt_sym_key.txt
Binary file not shown.
Binary file added encrypt_text.txt
Binary file not shown.
98 changes: 98 additions & 0 deletions file_work.py
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions private_key.pem
Original file line number Diff line number Diff line change
@@ -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-----
9 changes: 9 additions & 0 deletions public_key.pem
Original file line number Diff line number Diff line change
@@ -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-----
Loading