DVeProto

DVeProto

Server.System company

Протокол шифрования полезной нагрузки поверх WebSocket на базе X25519, HKDF-SHA256 и AES-256-GCM. Общее рукопожатие, компактный бинарный обмен и эталонные реализации для Python и браузера.

Протокол шифрования полезной нагрузки

X25519 · HKDF-SHA256 · AES-256-GCM. Два wire-режима: JSON 1.0 и binary 1.1. Рукопожатие совместимо между ними.

spec.json reference.py reference-client.js

Криптография (общая)

Одинакова для wire 1.0 и 1.1. Меняется только формат кадра после рукопожатия.

Рукопожатие

Всегда UTF-8 JSON, одинаково для обеих версий. Поле v рукопожатия = 1.

  1. Сервер: dve_hello с server_pk и опционально offer: ["1.0","1.1"].
  2. Клиент считает shared secret X25519 и ключи HKDF.
  3. Клиент: dve_client_ack с client_pk и select: "1.0" или "1.1". Без select → 1.0.
  4. Дальше только выбранный wire-формат.
{
  "type": "dve_hello",
  "proto": "DVeProto",
  "v": 1,
  "server_pk": "<base64 32 bytes>",
  "offer": ["1.0", "1.1"]
}

{
  "type": "dve_client_ack",
  "proto": "DVeProto",
  "v": 1,
  "client_pk": "<base64 32 bytes>",
  "select": "1.1"
}

Версии wire

Выберите версию, чтобы посмотреть формат данных после рукопожатия.

Wire 1.0 — JSON text frames

После handshake каждое сообщение — один WebSocket text frame с JSON. Ciphertext и nonce в Base64.

  • Транспорт: только text frames
  • Обёртка: type: "dve", proto, v: 1, n, c
  • Plaintext внутри AEAD — UTF-8 JSON объект
  • Режим по умолчанию, если клиент не указал select
{
  "type": "dve",
  "proto": "DVeProto",
  "v": 1,
  "n": "<base64 12-byte nonce>",
  "c": "<base64 AES-GCM ciphertext||tag>"
}

Подходит для каналов без binary frames и для максимальной совместимости со старыми клиентами.

Эталонный код

Референс-реализации в этой же папке — без привязки к конкретному продукту.

Python

session, ack = DVeClientSession.from_server_hello_text(hello_text, prefer="1.1")
frame = session.pack_outgoing({"dve_op": "ping"})

Браузер (ESM)

import { dveDeveloperHandshake } from './reference-client.js';
const { session, clientAckJson, wire } = await dveDeveloperHandshake(hello);
const out = await session.encryptOutgoing({ dve_op: 'ping' });

Конвенция APP_JSON

Совместимость

Клиенты без select работают на 1.0. Если обе стороны умеют 1.1 — выбирают binary. Смешанные пары остаются на JSON-кадрах.