lab5
1
lab5/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
key.txt
|
||||||
1
lab5/.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.14
|
||||||
75
lab5/README.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# Практическая работа №5 — Конфиденциальный обмен сообщениями
|
||||||
|
|
||||||
|
Клиент-серверное приложение для обмена сообщениями по TCP с поддержкой
|
||||||
|
шифрования 3DES-CBC (с затравкой), контроля целостности SHA-256 и
|
||||||
|
аутентификации отправителя HMAC-SHA256.
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ключ шифрования
|
||||||
|
|
||||||
|
Ключ хранится в текстовом файле (не менее 32 символов). Права на файл — только
|
||||||
|
чтение владельцем (`600`). Программа проверяет права при запуске и отказывается
|
||||||
|
работать, если файл доступен группе или другим пользователям.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl rand -hex 32 > key.txt
|
||||||
|
chmod 600 key.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
### Сервер
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run main.py server --port 9000 # без шифрования
|
||||||
|
uv run main.py server --port 9000 --encrypt # 3DES-CBC
|
||||||
|
uv run main.py server --port 9000 --encrypt --integrity # + SHA-256
|
||||||
|
uv run main.py server --port 9000 --encrypt --integrity --test-integrity # отправка с повреждённым хэшем
|
||||||
|
uv run main.py server --port 9000 --encrypt --hmac # 3DES + HMAC-SHA256
|
||||||
|
uv run main.py server --port 9000 --hmac # только HMAC (без шифрования)
|
||||||
|
uv run main.py server --port 9000 --key /path/to/key.txt --encrypt # другой файл ключа
|
||||||
|
```
|
||||||
|
|
||||||
|
### Клиент
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run main.py client 127.0.0.1 9000
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt --integrity
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt --integrity --test-integrity
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt --hmac
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt --hmac --test-integrity
|
||||||
|
```
|
||||||
|
|
||||||
|
## Режимы работы
|
||||||
|
|
||||||
|
| Флаг | Описание |
|
||||||
|
|------|----------|
|
||||||
|
| *(без флагов)* | Открытый текст, без проверки целостности |
|
||||||
|
| `--encrypt` | Шифрование 3DES-CBC с затравкой (соль + IV генерируются случайно для каждого сообщения) |
|
||||||
|
| `--integrity` | Контроль целостности — к сообщению прикладывается SHA-256 хэш открытого текста |
|
||||||
|
| `--hmac` | HMAC-SHA256 — контроль целостности + аутентификация отправителя (требует ключ, несовместим с `--integrity`) |
|
||||||
|
| `--test-integrity` | Режим тестирования: отправляется заведомо некорректный хэш/HMAC (требует `--integrity` или `--hmac`) |
|
||||||
|
|
||||||
|
## Анализ трафика с помощью tcpdump
|
||||||
|
|
||||||
|
Для наблюдения за передаваемыми данными удобно использовать `tcpdump`.
|
||||||
|
При работе на одной машине (loopback):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tcpdump -i lo -X -n tcp port 9000
|
||||||
|
```
|
||||||
|
|
||||||
|
При работе по сети (замените `eth0` на имя сетевого интерфейса):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tcpdump -i eth0 -X -n tcp port 9000
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Без шифрования** — в дампе видны сообщения открытым текстом (JSON с полем `"data": "текст сообщения"`).
|
||||||
|
- **С шифрованием** — в дампе видны только шифротекст, соль и IV в hex; читаемый текст отсутствует.
|
||||||
68
lab5/lab5.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Практическая работа №5
|
||||||
|
|
||||||
|
по дисциплине «Защита информации»
|
||||||
|
**Тема работы:** «Разработка клиент-серверного приложения для конфиденциального обмена сообщениями»
|
||||||
|
**Преподаватель:** Силиненко А.В.
|
||||||
|
**Email:** a_silinenko@mail.ru
|
||||||
|
|
||||||
|
## 1. Цель и задачи работы
|
||||||
|
|
||||||
|
### 1.1. Цель работы
|
||||||
|
|
||||||
|
Разработка клиент-серверного приложения для конфиденциального обмена сообщениями с использованием шифрования и контроля целостности.
|
||||||
|
|
||||||
|
### 1.2. Задачи работы
|
||||||
|
|
||||||
|
- получение базовых знаний по использованию криптографических функций библиотеки `crypto` в ОС Linux или другой библиотеки, обеспечивающей реализацию требований задания;
|
||||||
|
- разработка клиент-серверного приложения для обмена шифрованными сообщениями с контролем целостности;
|
||||||
|
- проверка работы приложения в различных режимах использования с помощью программы анализа трафика.
|
||||||
|
|
||||||
|
## 2. Требования к приложению
|
||||||
|
|
||||||
|
### 2.1. Общие требования
|
||||||
|
|
||||||
|
Разработать приложение типа «клиент-сервер», позволяющее обмениваться короткими сообщениями между клиентской и серверной частями приложения с обеспечением шифрования и контроля целостности.
|
||||||
|
|
||||||
|
### 2.2. Общие требования
|
||||||
|
|
||||||
|
- протокол взаимодействия: TCP;
|
||||||
|
- длина сообщения: не более 80 символов;
|
||||||
|
- полнодуплексный обмен сообщениями: возможность одновременного приема и передачи сообщений;
|
||||||
|
- IP-адрес и порт серверной части передается клиентской части приложения в качестве параметров запуска в командной строке;
|
||||||
|
- приложение должно быть способно функционировать как при запуске клиентской и серверной частей приложения на одном компьютере, так и на разных сетевых узлах;
|
||||||
|
- язык написания программы: любой.
|
||||||
|
|
||||||
|
### 2.3. Требования к функции шифрования
|
||||||
|
|
||||||
|
- приложение должно поддерживать функцию шифрования сообщений на основе симметричного шифрования с использованием библиотеки `crypto`, входящей в API `openssl`, или другой аналогичной библиотеки;
|
||||||
|
- алгоритм симметричного шифрования: согласно индивидуальному заданию;
|
||||||
|
В моём варианте это 3DES
|
||||||
|
- ключ шифрования длиной не менее 32 символов задается в файле;
|
||||||
|
- права доступа к файлу: чтение только владельцем;
|
||||||
|
- использование опции шифрования задается ключом командной строки при запуске программы.
|
||||||
|
|
||||||
|
### 2.4. Требования к функции контроля целостности
|
||||||
|
|
||||||
|
- приложение должно поддерживать функцию контроля целостности на основе подсчета хэш-значения передаваемого сообщения;
|
||||||
|
- алгоритм вычисления хэш-значения - в соответствии с индивидуальным заданием (см. практическую работу №2);
|
||||||
|
- использование опции контроля целостности задается ключом командной строки при запуске программы;
|
||||||
|
- предусмотреть режим тестирования, в котором при включенной опции контроля целостности отправляются сообщения с некорректным хэш-значением.
|
||||||
|
|
||||||
|
### 2.5. Необязательные требования
|
||||||
|
|
||||||
|
- реализовать шифрование с «затравкой» («солью»), обеспечивающей разные шифрованные сообщения при одном и том же открытом тексте;
|
||||||
|
- реализовать для разработанного приложения опцию выработки и использования сессионного ключа на основе алгоритма Диффи-Хеллмана вместо заранее заданного ключа.
|
||||||
|
|
||||||
|
## 3. Требования к отчету
|
||||||
|
|
||||||
|
### 3.1. В разделе отчета, посвященном данной работе, должны быть приведены
|
||||||
|
|
||||||
|
- актуальность темы работы в контексте курса;
|
||||||
|
- цели и задачи работы;
|
||||||
|
- краткое описание особенностей используемого алгоритма симметричного шифрования, а также шифрования «с затравкой» и алгоритма Диффи-Хеллмана, если реализованы соответствующие требования;
|
||||||
|
- команды компиляции и сборки исполняемых модулей приложения;
|
||||||
|
- описание процедуры проверки работы приложения с примерами, включая выводы программы анализа трафика, подтверждающие реализацию требований передачи сообщений без шифрования, с шифрованием, с шифрованием и контролем целостности;
|
||||||
|
- описание проверки опции контроля целостности, в которой отправляются сообщения с некорректным хэш-значением;
|
||||||
|
- описание проверки шифрования «с затравкой» и алгоритма Диффи-Хеллмана, если реализованы соответствующие требования;
|
||||||
|
- текст разработанного приложения (клиентской и серверной частей) с комментариями - в приложении к отчету;
|
||||||
|
- выводы по проделанной работе.
|
||||||
365
lab5/main.py
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
import stat
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from cryptography.hazmat.decrepit.ciphers.algorithms import TripleDES
|
||||||
|
from cryptography.hazmat.primitives.ciphers import Cipher, modes
|
||||||
|
from cryptography.hazmat.primitives import padding as sym_padding
|
||||||
|
|
||||||
|
MAX_MSG_LEN = 80
|
||||||
|
DEFAULT_KEY_FILE = "key.txt"
|
||||||
|
|
||||||
|
|
||||||
|
def check_key_permissions(path: str) -> None:
|
||||||
|
st = os.stat(path)
|
||||||
|
mode = st.st_mode
|
||||||
|
bad = stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH
|
||||||
|
if mode & bad:
|
||||||
|
current = oct(mode & 0o777)
|
||||||
|
print(f"[!] Key file permissions too open ({current}): {path}")
|
||||||
|
print(f" Run: chmod 600 {path}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def load_key(path: str) -> str:
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
print(f"[!] Key file not found: {path}")
|
||||||
|
sys.exit(1)
|
||||||
|
check_key_permissions(path)
|
||||||
|
with open(path) as f:
|
||||||
|
key = f.read().strip()
|
||||||
|
if len(key) < 32:
|
||||||
|
print(f"[!] Key must be at least 32 characters (got {len(key)})")
|
||||||
|
sys.exit(1)
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def derive_3des_key(file_key: str, salt: bytes) -> bytes:
|
||||||
|
return hashlib.sha256(file_key.encode() + salt).digest()[:24]
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_message(plaintext: str, file_key: str) -> tuple[bytes, bytes, bytes]:
|
||||||
|
salt = os.urandom(16)
|
||||||
|
key = derive_3des_key(file_key, salt)
|
||||||
|
iv = os.urandom(8)
|
||||||
|
|
||||||
|
padder = sym_padding.PKCS7(64).padder()
|
||||||
|
padded = padder.update(plaintext.encode()) + padder.finalize()
|
||||||
|
|
||||||
|
encryptor = Cipher(TripleDES(key), modes.CBC(iv)).encryptor()
|
||||||
|
ct = encryptor.update(padded) + encryptor.finalize()
|
||||||
|
return salt, iv, ct
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt_message(salt: bytes, iv: bytes, ct: bytes, file_key: str) -> str:
|
||||||
|
key = derive_3des_key(file_key, salt)
|
||||||
|
decryptor = Cipher(TripleDES(key), modes.CBC(iv)).decryptor()
|
||||||
|
padded = decryptor.update(ct) + decryptor.finalize()
|
||||||
|
|
||||||
|
unpadder = sym_padding.PKCS7(64).unpadder()
|
||||||
|
plaintext = unpadder.update(padded) + unpadder.finalize()
|
||||||
|
return plaintext.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def compute_hash(text: str) -> str:
|
||||||
|
return hashlib.sha256(text.encode()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def compute_hmac(file_key: str, text: str, salt: bytes) -> str:
|
||||||
|
return hmac.new(file_key.encode(), text.encode() + salt, hashlib.sha256).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def recv_exactly(sock: socket.socket, n: int) -> bytes | None:
|
||||||
|
buf = b""
|
||||||
|
while len(buf) < n:
|
||||||
|
chunk = sock.recv(n - len(buf))
|
||||||
|
if not chunk:
|
||||||
|
return None
|
||||||
|
buf += chunk
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def send_packet(sock: socket.socket, data: bytes) -> None:
|
||||||
|
sock.sendall(struct.pack("!I", len(data)) + data)
|
||||||
|
|
||||||
|
|
||||||
|
def recv_packet(sock: socket.socket) -> dict | None:
|
||||||
|
header = recv_exactly(sock, 4)
|
||||||
|
if header is None:
|
||||||
|
return None
|
||||||
|
length = struct.unpack("!I", header)[0]
|
||||||
|
payload = recv_exactly(sock, length)
|
||||||
|
if payload is None:
|
||||||
|
return None
|
||||||
|
return json.loads(payload.decode())
|
||||||
|
|
||||||
|
|
||||||
|
def do_send(
|
||||||
|
sock: socket.socket,
|
||||||
|
text: str,
|
||||||
|
file_key: str | None,
|
||||||
|
use_encrypt: bool,
|
||||||
|
use_integrity: bool,
|
||||||
|
use_hmac: bool,
|
||||||
|
test_integrity: bool,
|
||||||
|
) -> None:
|
||||||
|
msg: dict = {}
|
||||||
|
print(f" [TX] plaintext: {text}")
|
||||||
|
|
||||||
|
enc_salt: bytes | None = None
|
||||||
|
if use_encrypt:
|
||||||
|
assert file_key is not None
|
||||||
|
salt, iv, ct = encrypt_message(text, file_key)
|
||||||
|
enc_salt = salt
|
||||||
|
derived_hex = derive_3des_key(file_key, salt).hex()
|
||||||
|
msg["encrypted"] = True
|
||||||
|
msg["salt"] = salt.hex()
|
||||||
|
msg["iv"] = iv.hex()
|
||||||
|
msg["data"] = ct.hex()
|
||||||
|
print(f" [TX] salt: {salt.hex()}")
|
||||||
|
print(f" [TX] 3DES key: {derived_hex}")
|
||||||
|
print(f" [TX] IV: {iv.hex()}")
|
||||||
|
print(f" [TX] ciphertext: {ct.hex()}")
|
||||||
|
else:
|
||||||
|
msg["encrypted"] = False
|
||||||
|
msg["data"] = text
|
||||||
|
|
||||||
|
if use_integrity:
|
||||||
|
h = compute_hash(text)
|
||||||
|
if test_integrity:
|
||||||
|
h = hashlib.sha256(b"CORRUPTED_" + os.urandom(4)).hexdigest()
|
||||||
|
print(f" [TX] SHA-256: {h} (CORRUPTED!)")
|
||||||
|
else:
|
||||||
|
print(f" [TX] SHA-256: {h}")
|
||||||
|
msg["hash"] = h
|
||||||
|
|
||||||
|
if use_hmac:
|
||||||
|
assert file_key is not None
|
||||||
|
hmac_salt = enc_salt if enc_salt is not None else os.urandom(16)
|
||||||
|
h = compute_hmac(file_key, text, hmac_salt)
|
||||||
|
msg["hmac_salt"] = hmac_salt.hex()
|
||||||
|
if test_integrity:
|
||||||
|
h = hmac.new(b"WRONG_KEY", os.urandom(8), hashlib.sha256).hexdigest()
|
||||||
|
print(f" [TX] HMAC salt: {hmac_salt.hex()}")
|
||||||
|
print(f" [TX] HMAC-256: {h} (CORRUPTED!)")
|
||||||
|
else:
|
||||||
|
print(f" [TX] HMAC salt: {hmac_salt.hex()}")
|
||||||
|
print(f" [TX] HMAC-256: {h}")
|
||||||
|
msg["hmac"] = h
|
||||||
|
|
||||||
|
send_packet(sock, json.dumps(msg).encode())
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def do_recv(
|
||||||
|
msg: dict,
|
||||||
|
file_key: str | None,
|
||||||
|
) -> str | None:
|
||||||
|
encrypted = msg.get("encrypted", False)
|
||||||
|
|
||||||
|
if encrypted:
|
||||||
|
salt = bytes.fromhex(msg["salt"])
|
||||||
|
iv = bytes.fromhex(msg["iv"])
|
||||||
|
ct = bytes.fromhex(msg["data"])
|
||||||
|
print(f" [RX] ciphertext: {ct.hex()}")
|
||||||
|
print(f" [RX] salt: {salt.hex()}")
|
||||||
|
print(f" [RX] IV: {iv.hex()}")
|
||||||
|
if file_key is None:
|
||||||
|
print(" [RX] ERROR: message is encrypted but no key loaded")
|
||||||
|
return None
|
||||||
|
derived_hex = derive_3des_key(file_key, salt).hex()
|
||||||
|
print(f" [RX] 3DES key: {derived_hex}")
|
||||||
|
try:
|
||||||
|
text = decrypt_message(salt, iv, ct, file_key)
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [RX] decryption failed: {e}")
|
||||||
|
return None
|
||||||
|
print(f" [RX] decrypted: {text}")
|
||||||
|
else:
|
||||||
|
text = msg["data"]
|
||||||
|
print(f" [RX] plaintext: {text}")
|
||||||
|
|
||||||
|
if "hash" in msg:
|
||||||
|
received_hash = msg["hash"]
|
||||||
|
computed_hash = compute_hash(text)
|
||||||
|
ok = received_hash == computed_hash
|
||||||
|
print(f" [RX] recv hash: {received_hash}")
|
||||||
|
print(f" [RX] calc hash: {computed_hash}")
|
||||||
|
if ok:
|
||||||
|
print(" [RX] integrity: OK")
|
||||||
|
else:
|
||||||
|
print(" [RX] integrity: FAIL - message may have been tampered with!")
|
||||||
|
|
||||||
|
if "hmac" in msg:
|
||||||
|
hmac_salt = bytes.fromhex(msg["hmac_salt"])
|
||||||
|
received_hmac = msg["hmac"]
|
||||||
|
if file_key is None:
|
||||||
|
print(" [RX] ERROR: HMAC present but no key loaded")
|
||||||
|
else:
|
||||||
|
computed_h = compute_hmac(file_key, text, hmac_salt)
|
||||||
|
ok = hmac.compare_digest(received_hmac, computed_h)
|
||||||
|
print(f" [RX] HMAC salt: {hmac_salt.hex()}")
|
||||||
|
print(f" [RX] recv HMAC: {received_hmac}")
|
||||||
|
print(f" [RX] calc HMAC: {computed_h}")
|
||||||
|
if ok:
|
||||||
|
print(" [RX] HMAC auth: OK - sender verified")
|
||||||
|
else:
|
||||||
|
print(" [RX] HMAC auth: FAIL - sender NOT verified!")
|
||||||
|
|
||||||
|
print()
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def receiver_thread(
|
||||||
|
sock: socket.socket,
|
||||||
|
file_key: str | None,
|
||||||
|
stop_event: threading.Event,
|
||||||
|
) -> None:
|
||||||
|
try:
|
||||||
|
while not stop_event.is_set():
|
||||||
|
msg = recv_packet(sock)
|
||||||
|
if msg is None:
|
||||||
|
print("\n[*] Connection closed by remote side.")
|
||||||
|
stop_event.set()
|
||||||
|
break
|
||||||
|
do_recv(msg, file_key)
|
||||||
|
except OSError:
|
||||||
|
if not stop_event.is_set():
|
||||||
|
print("\n[*] Connection lost.")
|
||||||
|
stop_event.set()
|
||||||
|
|
||||||
|
|
||||||
|
def sender_thread(
|
||||||
|
sock: socket.socket,
|
||||||
|
file_key: str | None,
|
||||||
|
use_encrypt: bool,
|
||||||
|
use_integrity: bool,
|
||||||
|
use_hmac: bool,
|
||||||
|
test_integrity: bool,
|
||||||
|
stop_event: threading.Event,
|
||||||
|
) -> None:
|
||||||
|
try:
|
||||||
|
while not stop_event.is_set():
|
||||||
|
try:
|
||||||
|
text = input()
|
||||||
|
except EOFError:
|
||||||
|
stop_event.set()
|
||||||
|
break
|
||||||
|
if stop_event.is_set():
|
||||||
|
break
|
||||||
|
if len(text) > MAX_MSG_LEN:
|
||||||
|
print(f" [!] Message too long ({len(text)} > {MAX_MSG_LEN}), truncated.")
|
||||||
|
text = text[:MAX_MSG_LEN]
|
||||||
|
do_send(sock, text, file_key, use_encrypt, use_integrity, use_hmac, test_integrity)
|
||||||
|
except OSError:
|
||||||
|
if not stop_event.is_set():
|
||||||
|
stop_event.set()
|
||||||
|
|
||||||
|
|
||||||
|
def run_session(
|
||||||
|
sock: socket.socket,
|
||||||
|
addr: tuple,
|
||||||
|
file_key: str | None,
|
||||||
|
use_encrypt: bool,
|
||||||
|
use_integrity: bool,
|
||||||
|
use_hmac: bool,
|
||||||
|
test_integrity: bool,
|
||||||
|
) -> None:
|
||||||
|
flags = []
|
||||||
|
if use_encrypt:
|
||||||
|
flags.append("3DES")
|
||||||
|
if use_integrity:
|
||||||
|
flags.append("SHA-256")
|
||||||
|
if use_hmac:
|
||||||
|
flags.append("HMAC-SHA256")
|
||||||
|
if test_integrity:
|
||||||
|
flags.append("test-integrity")
|
||||||
|
mode_str = ", ".join(flags) if flags else "plaintext"
|
||||||
|
print(f"[*] Session with {addr[0]}:{addr[1]} [{mode_str}]")
|
||||||
|
print("[*] Type messages and press Enter to send. Ctrl+C / Ctrl+D to quit.\n")
|
||||||
|
|
||||||
|
stop = threading.Event()
|
||||||
|
rx = threading.Thread(target=receiver_thread, args=(sock, file_key, stop), daemon=True)
|
||||||
|
tx = threading.Thread(target=sender_thread, args=(sock, file_key, use_encrypt, use_integrity, use_hmac, test_integrity, stop), daemon=True)
|
||||||
|
rx.start()
|
||||||
|
tx.start()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while not stop.is_set():
|
||||||
|
stop.wait(0.5)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n[*] Interrupted.")
|
||||||
|
stop.set()
|
||||||
|
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
|
||||||
|
def run_server(args: argparse.Namespace) -> None:
|
||||||
|
file_key = load_key(args.key) if (args.encrypt or args.hmac) else None
|
||||||
|
|
||||||
|
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
srv.bind(("0.0.0.0", args.port))
|
||||||
|
srv.listen(1)
|
||||||
|
print(f"[*] Listening on 0.0.0.0:{args.port} ...")
|
||||||
|
|
||||||
|
conn, addr = srv.accept()
|
||||||
|
print(f"[*] Client connected: {addr[0]}:{addr[1]}")
|
||||||
|
srv.close()
|
||||||
|
run_session(conn, addr, file_key, args.encrypt, args.integrity, args.hmac, args.test_integrity)
|
||||||
|
|
||||||
|
|
||||||
|
def run_client(args: argparse.Namespace) -> None:
|
||||||
|
file_key = load_key(args.key) if (args.encrypt or args.hmac) else None
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock.connect((args.host, args.port))
|
||||||
|
print(f"[*] Connected to {args.host}:{args.port}")
|
||||||
|
run_session(sock, (args.host, args.port), file_key, args.encrypt, args.integrity, args.hmac, args.test_integrity)
|
||||||
|
|
||||||
|
|
||||||
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
|
parser = argparse.ArgumentParser(description="Encrypted messaging (3DES-CBC + SHA-256)")
|
||||||
|
sub = parser.add_subparsers(dest="role", required=True)
|
||||||
|
|
||||||
|
for name, sp in [("server", sub.add_parser("server", help="Start server")),
|
||||||
|
("client", sub.add_parser("client", help="Start client"))]:
|
||||||
|
if name == "server":
|
||||||
|
sp.add_argument("--port", type=int, required=True)
|
||||||
|
else:
|
||||||
|
sp.add_argument("host")
|
||||||
|
sp.add_argument("port", type=int)
|
||||||
|
sp.add_argument("--encrypt", action="store_true", help="Enable 3DES-CBC encryption")
|
||||||
|
sp.add_argument("--integrity", action="store_true", help="SHA-256 integrity check")
|
||||||
|
sp.add_argument("--hmac", action="store_true", help="HMAC-SHA256 integrity + authentication")
|
||||||
|
sp.add_argument("--test-integrity", action="store_true", help="Send corrupted hash/HMAC")
|
||||||
|
sp.add_argument("--key", default=DEFAULT_KEY_FILE, help="Path to key file (default: key.txt)")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
args = build_parser().parse_args()
|
||||||
|
if args.integrity and args.hmac:
|
||||||
|
print("[!] --integrity and --hmac are mutually exclusive")
|
||||||
|
sys.exit(1)
|
||||||
|
if args.test_integrity and not (args.integrity or args.hmac):
|
||||||
|
print("[!] --test-integrity requires --integrity or --hmac")
|
||||||
|
sys.exit(1)
|
||||||
|
if args.role == "server":
|
||||||
|
run_server(args)
|
||||||
|
else:
|
||||||
|
run_client(args)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
9
lab5/pyproject.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[project]
|
||||||
|
name = "lab5"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.14"
|
||||||
|
dependencies = [
|
||||||
|
"cryptography>=46.0.6",
|
||||||
|
]
|
||||||
109
lab5/uv.lock
generated
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 3
|
||||||
|
requires-python = ">=3.14"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cffi"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cryptography"
|
||||||
|
version = "46.0.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a4/ba/04b1bd4218cbc58dc90ce967106d51582371b898690f3ae0402876cc4f34/cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", size = 750542, upload-time = "2026-03-25T23:34:53.396Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/23/9285e15e3bc57325b0a72e592921983a701efc1ee8f91c06c5f0235d86d9/cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", size = 7176401, upload-time = "2026-03-25T23:33:22.096Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/60/f8/e61f8f13950ab6195b31913b42d39f0f9afc7d93f76710f299b5ec286ae6/cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", size = 4275275, upload-time = "2026-03-25T23:33:23.844Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/19/69/732a736d12c2631e140be2348b4ad3d226302df63ef64d30dfdb8db7ad1c/cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", size = 4425320, upload-time = "2026-03-25T23:33:25.703Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", size = 4278082, upload-time = "2026-03-25T23:33:27.423Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/ba/d5e27f8d68c24951b0a484924a84c7cdaed7502bac9f18601cd357f8b1d2/cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", size = 4926514, upload-time = "2026-03-25T23:33:29.206Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", size = 4457766, upload-time = "2026-03-25T23:33:30.834Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/59/562be1e653accee4fdad92c7a2e88fced26b3fdfce144047519bbebc299e/cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", size = 3986535, upload-time = "2026-03-25T23:33:33.02Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/8b/b1ebfeb788bf4624d36e45ed2662b8bd43a05ff62157093c1539c1288a18/cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", size = 4277618, upload-time = "2026-03-25T23:33:34.567Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dd/52/a005f8eabdb28df57c20f84c44d397a755782d6ff6d455f05baa2785bd91/cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", size = 4890802, upload-time = "2026-03-25T23:33:37.034Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/4d/8e7d7245c79c617d08724e2efa397737715ca0ec830ecb3c91e547302555/cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", size = 4457425, upload-time = "2026-03-25T23:33:38.904Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1d/5c/f6c3596a1430cec6f949085f0e1a970638d76f81c3ea56d93d564d04c340/cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", size = 4405530, upload-time = "2026-03-25T23:33:40.842Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/c9/9f9cea13ee2dbde070424e0c4f621c091a91ffcc504ffea5e74f0e1daeff/cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", size = 4667896, upload-time = "2026-03-25T23:33:42.781Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ad/b5/1895bc0821226f129bc74d00eccfc6a5969e2028f8617c09790bf89c185e/cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", size = 3026348, upload-time = "2026-03-25T23:33:45.021Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c3/f8/c9bcbf0d3e6ad288b9d9aa0b1dee04b063d19e8c4f871855a03ab3a297ab/cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", size = 3483896, upload-time = "2026-03-25T23:33:46.649Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/41/3a578f7fd5c70611c0aacba52cd13cb364a5dee895a5c1d467208a9380b0/cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", size = 7117147, upload-time = "2026-03-25T23:33:48.249Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/87/887f35a6fca9dde90cad08e0de0c89263a8e59b2d2ff904fd9fcd8025b6f/cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", size = 4266221, upload-time = "2026-03-25T23:33:49.874Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/a8/0a90c4f0b0871e0e3d1ed126aed101328a8a57fd9fd17f00fb67e82a51ca/cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", size = 4408952, upload-time = "2026-03-25T23:33:52.128Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/0b/b239701eb946523e4e9f329336e4ff32b1247e109cbab32d1a7b61da8ed7/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", size = 4270141, upload-time = "2026-03-25T23:33:54.11Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0f/a8/976acdd4f0f30df7b25605f4b9d3d89295351665c2091d18224f7ad5cdbf/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", size = 4904178, upload-time = "2026-03-25T23:33:55.725Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b1/1b/bf0e01a88efd0e59679b69f42d4afd5bced8700bb5e80617b2d63a3741af/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", size = 4441812, upload-time = "2026-03-25T23:33:57.364Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/8b/11df86de2ea389c65aa1806f331cae145f2ed18011f30234cc10ca253de8/cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", size = 3963923, upload-time = "2026-03-25T23:33:59.361Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/91/e0/207fb177c3a9ef6a8108f234208c3e9e76a6aa8cf20d51932916bd43bda0/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", size = 4269695, upload-time = "2026-03-25T23:34:00.909Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/21/5e/19f3260ed1e95bced52ace7501fabcd266df67077eeb382b79c81729d2d3/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4", size = 4869785, upload-time = "2026-03-25T23:34:02.796Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/38/cd7864d79aa1d92ef6f1a584281433419b955ad5a5ba8d1eb6c872165bcb/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", size = 4441404, upload-time = "2026-03-25T23:34:04.35Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/09/0a/4fe7a8d25fed74419f91835cf5829ade6408fd1963c9eae9c4bce390ecbb/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", size = 4397549, upload-time = "2026-03-25T23:34:06.342Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5f/a0/7d738944eac6513cd60a8da98b65951f4a3b279b93479a7e8926d9cd730b/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", size = 4651874, upload-time = "2026-03-25T23:34:07.916Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/f1/c2326781ca05208845efca38bf714f76939ae446cd492d7613808badedf1/cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", size = 3001511, upload-time = "2026-03-25T23:34:09.892Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c9/57/fe4a23eb549ac9d903bd4698ffda13383808ef0876cc912bcb2838799ece/cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", size = 3471692, upload-time = "2026-03-25T23:34:11.613Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", size = 7162776, upload-time = "2026-03-25T23:34:13.308Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/b3/dc27efd8dcc4bff583b3f01d4a3943cd8b5821777a58b3a6a5f054d61b79/cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", size = 4270529, upload-time = "2026-03-25T23:34:15.019Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/05/e8d0e6eb4f0d83365b3cb0e00eb3c484f7348db0266652ccd84632a3d58d/cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", size = 4414827, upload-time = "2026-03-25T23:34:16.604Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/97/daba0f5d2dc6d855e2dcb70733c812558a7977a55dd4a6722756628c44d1/cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", size = 4271265, upload-time = "2026-03-25T23:34:18.586Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/06/fe1fce39a37ac452e58d04b43b0855261dac320a2ebf8f5260dd55b201a9/cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", size = 4916800, upload-time = "2026-03-25T23:34:20.561Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", size = 4448771, upload-time = "2026-03-25T23:34:22.406Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/b3/0796998056a66d1973fd52ee89dc1bb3b6581960a91ad4ac705f182d398f/cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", size = 3978333, upload-time = "2026-03-25T23:34:24.281Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c5/3d/db200af5a4ffd08918cd55c08399dc6c9c50b0bc72c00a3246e099d3a849/cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", size = 4271069, upload-time = "2026-03-25T23:34:25.895Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d7/18/61acfd5b414309d74ee838be321c636fe71815436f53c9f0334bf19064fa/cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", size = 4878358, upload-time = "2026-03-25T23:34:27.67Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/65/5bf43286d566f8171917cae23ac6add941654ccf085d739195a4eacf1674/cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", size = 4448061, upload-time = "2026-03-25T23:34:29.375Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e0/25/7e49c0fa7205cf3597e525d156a6bce5b5c9de1fd7e8cb01120e459f205a/cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", size = 4399103, upload-time = "2026-03-25T23:34:32.036Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/44/46/466269e833f1c4718d6cd496ffe20c56c9c8d013486ff66b4f69c302a68d/cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", size = 4659255, upload-time = "2026-03-25T23:34:33.679Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/09/ddc5f630cc32287d2c953fc5d32705e63ec73e37308e5120955316f53827/cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", size = 3010660, upload-time = "2026-03-25T23:34:35.418Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1b/82/ca4893968aeb2709aacfb57a30dec6fa2ab25b10fa9f064b8882ce33f599/cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", size = 3471160, upload-time = "2026-03-25T23:34:37.191Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lab5"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [{ name = "cryptography", specifier = ">=46.0.6" }]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pycparser"
|
||||||
|
version = "3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
|
||||||
|
]
|
||||||
BIN
report/img/lab5-enc-int.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
report/img/lab5-enc-tcpdump.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
report/img/lab5-enc.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
report/img/lab5-hmac-fail.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
report/img/lab5-hmac.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
report/img/lab5-plain-tcpdump.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
report/img/lab5-plain.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
report/img/lab5-salt.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
report/img/lab5-test-int.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
@@ -178,6 +178,7 @@
|
|||||||
\item Практическая работа №2. Разработка и исследование системы аутентификации и авторизации. Данная практическая работа посвящена разработке системы доступа пользователей к конфиденциальным данным и исследованию стойкости паролей к атаке методом грубой силы. В ходе выполнения работы реализованы утилита управления пользователями, утилита доступа к конфиденциальным данным и программа перебора паролей, а также проведено экспериментальное исследование зависимости времени взлома от длины пароля.
|
\item Практическая работа №2. Разработка и исследование системы аутентификации и авторизации. Данная практическая работа посвящена разработке системы доступа пользователей к конфиденциальным данным и исследованию стойкости паролей к атаке методом грубой силы. В ходе выполнения работы реализованы утилита управления пользователями, утилита доступа к конфиденциальным данным и программа перебора паролей, а также проведено экспериментальное исследование зависимости времени взлома от длины пароля.
|
||||||
\item Практическая работа №3. Реализация моделей дискреционного и мандатного управления доступом. Данная практическая работа посвящена расширению системы из работы №2 путём реализации моделей DAC (дискреционный доступ) и MAC (мандатный доступ) на основе модели Белла–Лападулы.
|
\item Практическая работа №3. Реализация моделей дискреционного и мандатного управления доступом. Данная практическая работа посвящена расширению системы из работы №2 путём реализации моделей DAC (дискреционный доступ) и MAC (мандатный доступ) на основе модели Белла–Лападулы.
|
||||||
\item Практическая работа №4. Межсетевое экранирование средствами \texttt{iptables}. Данная практическая работа посвящена настройке межсетевого экрана в Linux, формированию политики фильтрации сетевого трафика и экспериментальной проверке пропуска разрешённых соединений и блокировки запрещённых пакетов с использованием \texttt{tcpdump}.
|
\item Практическая работа №4. Межсетевое экранирование средствами \texttt{iptables}. Данная практическая работа посвящена настройке межсетевого экрана в Linux, формированию политики фильтрации сетевого трафика и экспериментальной проверке пропуска разрешённых соединений и блокировки запрещённых пакетов с использованием \texttt{tcpdump}.
|
||||||
|
\item Практическая работа №5. Разработка клиент-серверного приложения для конфиденциального обмена сообщениями. Данная практическая работа посвящена разработке TCP-приложения с поддержкой шифрования 3DES-CBC с затравкой и контроля целостности на основе SHA-256, а также проверке корректности шифрования с помощью анализа трафика.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
@@ -956,6 +957,183 @@ $ sudo tcpdump -i any -n icmp
|
|||||||
В ходе практической работы №4 на стенде из двух виртуальных машин VirtualBox настроена политика межсетевого экранирования средствами \texttt{iptables}. Реализована схема с политикой \texttt{DROP} по умолчанию и разрешающими правилами для loopback, DNS, исходящего ping, входящего ping от адреса \texttt{192.168.100.2} и HTTP/HTTPS. Экспериментальная проверка подтвердила пропуск разрешённого трафика и блокировку соединений, не описанных в политике. Анализ трафика утилитой \texttt{tcpdump} продемонстрировал соответствие наблюдаемой сетевой активности заданным правилам фильтрации.
|
В ходе практической работы №4 на стенде из двух виртуальных машин VirtualBox настроена политика межсетевого экранирования средствами \texttt{iptables}. Реализована схема с политикой \texttt{DROP} по умолчанию и разрешающими правилами для loopback, DNS, исходящего ping, входящего ping от адреса \texttt{192.168.100.2} и HTTP/HTTPS. Экспериментальная проверка подтвердила пропуск разрешённого трафика и блокировку соединений, не описанных в политике. Анализ трафика утилитой \texttt{tcpdump} продемонстрировал соответствие наблюдаемой сетевой активности заданным правилам фильтрации.
|
||||||
|
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\section{Разработка клиент-серверного приложения для конфиденциального обмена сообщениями}
|
||||||
|
|
||||||
|
\subsection{Актуальность темы}
|
||||||
|
|
||||||
|
Обеспечение конфиденциальности и целостности данных при передаче по сети является одной из ключевых задач информационной безопасности. Даже при использовании защищённых протоколов транспортного уровня понимание механизмов симметричного шифрования и контроля целостности на уровне приложения позволяет проектировать системы с дополнительным эшелоном защиты. Практическая реализация клиент-серверного приложения с шифрованием и хэш-контролем в рамках курса <<Защита информации>> закрепляет навыки работы с криптографическими примитивами и демонстрирует их влияние на передаваемый трафик.
|
||||||
|
|
||||||
|
\subsection{Цели и задачи работы}
|
||||||
|
|
||||||
|
Цель работы: разработка клиент-серверного приложения для обмена короткими сообщениями по протоколу TCP с обеспечением шифрования и контроля целостности.
|
||||||
|
|
||||||
|
Задачи работы:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Получить базовые знания по использованию криптографических функций библиотеки \texttt{cryptography} в Python.
|
||||||
|
\item Разработать клиент-серверное приложение для обмена шифрованными сообщениями с контролем целостности.
|
||||||
|
\item Проверить работу приложения в различных режимах, в том числе с помощью программы анализа трафика \texttt{tcpdump}.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\subsection{Описание алгоритма шифрования}
|
||||||
|
|
||||||
|
\textbf{3DES (Triple DES)} — симметричный блочный шифр, основанный на трёхкратном применении алгоритма DES в режиме EDE (Encrypt–Decrypt–Encrypt) с тремя независимыми подключами. Размер блока — 64 бита (8 байт), длина ключа — 192 бита (24 байта, из которых 168 бит являются эффективными ключевыми битами, а оставшиеся 24 бита — биты чётности). Несмотря на то что 3DES считается устаревшим и уступает AES по производительности, он по-прежнему обеспечивает достаточный уровень стойкости для учебных задач.
|
||||||
|
|
||||||
|
В разработанном приложении используется режим сцепления блоков \textbf{CBC} (Cipher Block Chaining): каждый блок открытого текста перед шифрованием складывается по модулю 2 с предыдущим блоком шифротекста (для первого блока — с вектором инициализации IV). Это обеспечивает зависимость каждого блока шифротекста от всех предшествующих блоков, затрудняя анализ повторяющихся фрагментов. Дополнение до границы блока выполняется по схеме PKCS7.
|
||||||
|
|
||||||
|
\textbf{Шифрование с затравкой (солью).} Для каждого сообщения генерируется случайная 16-байтовая затравка (salt). Ключ 3DES длиной 24 байта вычисляется как первые 24 байта хэша SHA-256 от конкатенации мастер-ключа из файла и затравки: $K_{\mathrm{3DES}} = \mathrm{SHA\text{-}256}(K_{\mathrm{file}} \mathbin\| \mathrm{salt})[{:}24]$. Кроме того, для каждого сообщения генерируется случайный 8-байтовый IV. Затравка и IV передаются вместе с шифротекстом в открытом виде, что позволяет получателю воспроизвести ключ. Благодаря уникальности затравки и IV одинаковые открытые тексты порождают различные шифротексты, что исключает атаки на основе повторения.
|
||||||
|
|
||||||
|
\textbf{Контроль целостности} реализован с помощью хэш-функции SHA-256 (в соответствии с индивидуальным заданием из практической работы №2). При включённой опции контроля целостности отправитель вычисляет хэш открытого текста сообщения и передаёт его вместе с данными. Получатель вычисляет хэш самостоятельно и сравнивает с полученным значением; при расхождении выводится предупреждение о нарушении целостности.
|
||||||
|
|
||||||
|
\textbf{HMAC-SHA256.} В качестве альтернативы простому SHA-256 реализован режим HMAC (Hash-based Message Authentication Code) на основе SHA-256. В отличие от обычного хэша, HMAC использует секретный ключ: $\mathrm{HMAC} = \mathrm{HMAC\text{-}SHA256}(K_{\mathrm{file}},\; \mathrm{plaintext} \mathbin\| \mathrm{salt})$. Это даёт два преимущества: (1)~получатель может убедиться, что отправитель владеет тем же секретным ключом (аутентификация), а не только в том, что сообщение не было изменено; (2)~случайная затравка, подмешиваемая к сообщению, обеспечивает различные значения HMAC для одинаковых открытых текстов. Режимы \texttt{-{}-integrity} (SHA-256) и \texttt{-{}-hmac} (HMAC-SHA256) являются взаимоисключающими.
|
||||||
|
|
||||||
|
\subsection{Описание реализации}
|
||||||
|
|
||||||
|
Приложение реализовано на языке Python~3.14 в виде единого файла \texttt{main.py} (исходный код приведён в приложении~9). Для криптографических операций используется библиотека \texttt{cryptography}. Управление зависимостями осуществляется менеджером \texttt{uv}.
|
||||||
|
|
||||||
|
\textbf{Протокол обмена.} Сообщения передаются по TCP в формате: 4~байта длины (big-endian) + JSON-объект. Структура JSON-объекта:
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
{
|
||||||
|
"encrypted": true/false,
|
||||||
|
"salt": "hex (16 байт)",
|
||||||
|
"iv": "hex (8 байт)",
|
||||||
|
"data": "hex шифротекст / открытый текст",
|
||||||
|
"hash": "SHA-256 hex (если включён контроль)"
|
||||||
|
}
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
\textbf{Полнодуплексный обмен} обеспечивается двумя потоками: один читает ввод пользователя и отправляет сообщения, второй принимает входящие сообщения и выводит их на экран.
|
||||||
|
|
||||||
|
\textbf{Режимы запуска} задаются ключами командной строки: \texttt{-{}-encrypt} включает шифрование 3DES-CBC, \texttt{-{}-integrity} включает контроль целостности SHA-256, \texttt{-{}-hmac} включает контроль целостности и аутентификацию HMAC-SHA256 (несовместим с \texttt{-{}-integrity}), \texttt{-{}-test-integrity} активирует режим отправки сообщений с заведомо некорректным хэш-значением (требует \texttt{-{}-integrity} или \texttt{-{}-hmac}).
|
||||||
|
|
||||||
|
\textbf{Защита ключа.} Мастер-ключ считывается из файла (по умолчанию \texttt{key.txt}). При запуске программа проверяет права доступа к файлу ключа и завершает работу с ошибкой, если файл доступен для чтения группе или другим пользователям (права более открытые, чем \texttt{600}).
|
||||||
|
|
||||||
|
\subsection{Команды сборки и запуска}
|
||||||
|
|
||||||
|
Установка зависимостей:
|
||||||
|
\begin{verbatim}
|
||||||
|
uv sync
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
Создание файла ключа:
|
||||||
|
\begin{verbatim}
|
||||||
|
openssl rand -hex 32 > key.txt
|
||||||
|
chmod 600 key.txt
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
Запуск сервера и клиента (примеры):
|
||||||
|
\begin{verbatim}
|
||||||
|
uv run main.py server --port 9000
|
||||||
|
uv run main.py client 127.0.0.1 9000
|
||||||
|
|
||||||
|
uv run main.py server --port 9000 --encrypt
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt
|
||||||
|
|
||||||
|
uv run main.py server --port 9000 --encrypt --integrity
|
||||||
|
uv run main.py client 127.0.0.1 9000 --encrypt --integrity
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
\subsection{Проверка работы приложения}
|
||||||
|
|
||||||
|
\subsubsection{Передача сообщений без шифрования}
|
||||||
|
|
||||||
|
При запуске без флагов сообщения передаются открытым текстом. На рисунке~\ref{fig:lab5-plain} показан вывод серверной и клиентской частей приложения.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.8\linewidth]{img/lab5-plain.png}
|
||||||
|
\caption{Обмен сообщениями без шифрования}
|
||||||
|
\label{fig:lab5-plain}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Анализ трафика утилитой \texttt{tcpdump} (рис.~\ref{fig:lab5-plain-tcpdump}) подтверждает, что текст сообщения передаётся в открытом виде и может быть прочитан непосредственно из дампа пакетов.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-plain-tcpdump.png}
|
||||||
|
\caption{Дамп трафика (\texttt{tcpdump}) при передаче без шифрования — текст виден}
|
||||||
|
\label{fig:lab5-plain-tcpdump}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsubsection{Передача сообщений с шифрованием}
|
||||||
|
|
||||||
|
При включённой опции \texttt{-{}-encrypt} сообщения шифруются алгоритмом 3DES-CBC с затравкой. На рисунке~\ref{fig:lab5-enc} показан вывод приложения: видны параметры шифрования (соль, производный ключ, IV, шифротекст) и результат расшифровки.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-enc.png}
|
||||||
|
\caption{Обмен сообщениями с шифрованием 3DES-CBC}
|
||||||
|
\label{fig:lab5-enc}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Дамп трафика (рис.~\ref{fig:lab5-enc-tcpdump}) показывает, что в пакетах присутствует только шифротекст в виде hex-строк; читаемый текст сообщения отсутствует.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-enc-tcpdump.png}
|
||||||
|
\caption{Дамп трафика при передаче с шифрованием — текст не виден}
|
||||||
|
\label{fig:lab5-enc-tcpdump}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsubsection{Шифрование с контролем целостности}
|
||||||
|
|
||||||
|
При одновременном использовании флагов \texttt{-{}-encrypt} и \texttt{-{}-integrity} к зашифрованному сообщению добавляется хэш SHA-256 открытого текста. На стороне получателя после расшифровки вычисляется собственный хэш и сравнивается с полученным (рис.~\ref{fig:lab5-enc-int}).
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-enc-int.png}
|
||||||
|
\caption{Обмен сообщениями с шифрованием и контролем целостности}
|
||||||
|
\label{fig:lab5-enc-int}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsubsection{Тестирование контроля целостности с некорректным хэшем}
|
||||||
|
|
||||||
|
В режиме \texttt{-{}-test-integrity} отправитель намеренно передаёт некорректный хэш. Получатель обнаруживает расхождение и выводит предупреждение (рис.~\ref{fig:lab5-test-int}).
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-test-int.png}
|
||||||
|
\caption{Обнаружение некорректного хэш-значения}
|
||||||
|
\label{fig:lab5-test-int}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsubsection{Демонстрация шифрования с затравкой}
|
||||||
|
|
||||||
|
При отправке одного и того же сообщения дважды шифротексты различаются благодаря случайной затравке и IV (рис.~\ref{fig:lab5-salt}).
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-salt.png}
|
||||||
|
\caption{Разные шифротексты для одинаковых сообщений (эффект затравки)}
|
||||||
|
\label{fig:lab5-salt}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsubsection{Контроль целостности и аутентификация с HMAC-SHA256}
|
||||||
|
|
||||||
|
При использовании флага \texttt{-{}-hmac} вместо \texttt{-{}-integrity} к каждому сообщению прикладывается код HMAC-SHA256, вычисленный с использованием секретного ключа и случайной затравки. На рисунке~\ref{fig:lab5-hmac} показан обмен сообщениями в режиме \texttt{-{}-encrypt -{}-hmac}: видны HMAC-затравка, вычисленный HMAC на стороне отправителя и результат проверки на стороне получателя. При отправке одного и того же сообщения повторно значение HMAC отличается благодаря новой затравке.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-hmac.png}
|
||||||
|
\caption{Обмен сообщениями с HMAC-SHA256: аутентификация и контроль целостности}
|
||||||
|
\label{fig:lab5-hmac}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
На рисунке~\ref{fig:lab5-hmac-fail} показана проверка режима \texttt{-{}-test-integrity} совместно с \texttt{-{}-hmac}: отправитель передаёт намеренно некорректный HMAC, получатель обнаруживает несоответствие и сообщает о неудачной аутентификации.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.85\linewidth]{img/lab5-hmac-fail.png}
|
||||||
|
\caption{Обнаружение некорректного HMAC — отправитель не аутентифицирован}
|
||||||
|
\label{fig:lab5-hmac-fail}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsection{Выводы}
|
||||||
|
|
||||||
|
В ходе практической работы №5 разработано клиент-серверное приложение для конфиденциального обмена сообщениями по протоколу TCP. Реализовано шифрование 3DES-CBC с затравкой, обеспечивающей различные шифротексты при одинаковых открытых текстах, контроль целостности на основе хэш-функции SHA-256 и режим HMAC-SHA256, обеспечивающий одновременно контроль целостности и аутентификацию отправителя. Экспериментальная проверка с помощью \texttt{tcpdump} подтвердила, что при включённом шифровании содержимое сообщений не передаётся в открытом виде, а при включённом контроле целостности получатель успешно обнаруживает намеренно повреждённые сообщения.
|
||||||
|
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
\section*{Заключение}
|
\section*{Заключение}
|
||||||
\addcontentsline{toc}{section}{Заключение}
|
\addcontentsline{toc}{section}{Заключение}
|
||||||
@@ -968,6 +1146,8 @@ $ sudo tcpdump -i any -n icmp
|
|||||||
|
|
||||||
В ходе выполнения практической работы №4 на стенде из двух виртуальных машин VirtualBox настроена политика межсетевого экранирования средствами \texttt{iptables}. Реализованы правила фильтрации, разрешающие loopback-трафик, DNS, ICMP и HTTP/HTTPS, а все прочие соединения блокируются. Корректность работы правил подтверждена тестовыми соединениями и анализом пакетов утилитой \texttt{tcpdump}.
|
В ходе выполнения практической работы №4 на стенде из двух виртуальных машин VirtualBox настроена политика межсетевого экранирования средствами \texttt{iptables}. Реализованы правила фильтрации, разрешающие loopback-трафик, DNS, ICMP и HTTP/HTTPS, а все прочие соединения блокируются. Корректность работы правил подтверждена тестовыми соединениями и анализом пакетов утилитой \texttt{tcpdump}.
|
||||||
|
|
||||||
|
В ходе выполнения практической работы №5 разработано клиент-серверное приложение для конфиденциального обмена сообщениями по протоколу TCP. Реализовано шифрование 3DES-CBC с затравкой, контроль целостности SHA-256 и режим HMAC-SHA256 для аутентификации отправителя. Анализ трафика утилитой \texttt{tcpdump} подтвердил, что при включённом шифровании содержимое сообщений не доступно в открытом виде, а режим тестирования продемонстрировал корректное обнаружение нарушений целостности.
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
\printbibliography[heading=bibintoc]
|
\printbibliography[heading=bibintoc]
|
||||||
|
|
||||||
@@ -1021,4 +1201,11 @@ $ sudo tcpdump -i any -n icmp
|
|||||||
\addcontentsline{toc}{section}{Приложение 8}
|
\addcontentsline{toc}{section}{Приложение 8}
|
||||||
\lstinputlisting{../lab3/setup.sh}
|
\lstinputlisting{../lab3/setup.sh}
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\section*{Приложение 9}
|
||||||
|
\subsubsection*{main.py}
|
||||||
|
\addcontentsline{toc}{section}{Приложение 9}
|
||||||
|
\label{app:lab5-main}
|
||||||
|
\lstinputlisting{../lab5/main.py}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|||||||