You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3.8 KiB

STCP Server — приём и рукопожатие соединений

1. Назначение

STCP Server — серверная сторона протокола STCP. Создаёт слушающий TCP-сокет на указанном порту, принимает входящие соединения, выполняет серверную часть X25519-рукопожатия и поднимает зашифрованный канал AES-CTR для обмена сообщениями.

Использует общую структуру struct stcp_conn из stcp.h.

2. Как пользоваться

struct stcp_server *srv = stcp_server_create(ua, port, &my_keys,
    on_connect_cb, conn_arg,   // вызывается после успешного рукопожатия
    on_close_cb, close_arg);   // вызывается при закрытии/ошибке

// ... use ...

stcp_server_destroy(srv);

После завершения рукопожатия соединение переходит в STCP_STATE_DATA, вызывается connect_cb. Вышестоящий код может слать сообщения через tx_queue — они будут зашифрованы с CRC32 и отправлены. Входящие расшифрованные сообщения попадают в rx_queue.

Ключевые нюансы:

  • Сервер принимает клиентский pubkey+salt (обфусцированный), извлекает pubkey через sc_obfuscate_pubkey, выполняет ECDH.
  • Отправляет ответ: статус OK + padding + CRC32, всё зашифровано AES-CTR.
  • После рукопожатая трафик шифруется потоковым AES-CTR (XOR), для каждого направления — свой stream.
  • Рукопожатие обрабатывается в два этапа: process_client_handshake (извлечение ключа, дешифровка) → finish_client_handshake (отправка ответа, переход в DATA).

3. API

stcp_server — внутренняя структура

Слушающий сокет, ключи сервера, коллбэки connect_cb / close_cb. Не экспортируется, создаётся только через stcp_server_create.

Функции

  • stcp_server_create(ua, port, keys, connect_cb, arg, close_cb, close_arg) — создать сервер: открыть TCP-сокет, bind к порту (IPV4, INADDR_ANY), listen(16), зарегистрировать accept-коллбэк. При приёме соединения создаёт struct stcp_conn в состоянии STCP_STATE_HS_SERVER_WAIT.
  • stcp_server_destroy(srv) — закрыть слушающий сокет, освободить память.

Протокол рукопожатия (серверная сторона)

  1. Сервер читает SC_PUBKEY_ENC_SIZE + STCP_HS_ENC_CLIENT байт (pubkey+salt + зашифрованные padding_size + CRC32).
  2. Деобфусцирует клиентский pubkey (sc_obfuscate_pubkey, salt XOR с SHA256(salt||server_pubkey)).
  3. Выполняет ECDH (sc_init_ctx + sc_set_peer_public_key) → получает session_key, инициализирует stream_send/stream_recv.
  4. Расшифровывает padding_size, проверяет CRC32, ожидает padding-байты.
  5. Формирует ответ: salt2(8) + обфусцированный серверный pubkey(32) + status=OK(1) + padding_size(2) + CRC32(4) + padding(8). Всё кроме salt2 зашифровано sc_stream_xor.
  6. Переходит в STCP_STATE_DATA, вызывает on_ready (== connect_cb).