Криптография
Всё, что передаётся через Velum, защищено сквозным гибридным шифрованием: классическим (X25519) и постквантовым (ML-KEM-768). Если один из алгоритмов будет взломан, второй продолжит защищать сообщение.
Личность, кошелёк и устройства
Всё начинается с фразы восстановления из 24 слов (BIP-39, 256 бит). Список слов соответствует языку устройства; для русского используется английский, потому что официального русского списка нет.
семя = BIP39.mnemonicToSeed(фраза) 64 байта
личность = HKDF-SHA512(семя, info = "velum/v2/identity") ed25519
кошелёк = HKDF-SHA512(семя, info = "m/44'/7420'/0'/0'/0'") ed25519
ящик = HKDF-SHA512(семя, info = "velum/v2/mailbox") 32 Б
- Личность подписывает твой профиль и список устройств. Её знают только твои контакты (через QR-код или ссылку); в сеть в открытом виде она никогда не уходит.
- Кошелёк подписывает транзакции. Это отдельный ключ, чтобы никто не мог связать чаты и платежи.
- У каждого устройства свой случайный ключ, который никогда его не покидает: ed25519 (подпись), X25519 и ML-KEM-768 (шифрование).
Адреса — это vel + base58 открытого ключа ed25519 (32 байта). См. Кошельки и биржи.
Список устройств
Каждый аккаунт рассылает контактам внутри зашифрованных сообщений типа profile список, подписанный личностью:
DeviceList = { identity, devices: [{ id, sign, x25519, kem, mailboxSeed, added, name }], ts, sig }
Список никогда не публикуется в блокчейне. В нём может быть до 5 устройств. При отключении устройства подписывается новый список без него и меняется секрет ящика.
Гибридный конверт
Для каждого устройства-получателя:
eph = эфемерный ключ X25519
(kemCt, kemSs) = ML-KEM-768.encapsulate(устройство.kem)
ключ = HKDF-SHA512(ikm = X25519(eph, устройство.x25519) ‖ kemSs,
salt = eph.pub ‖ kemCt,
info = "velum/v2/envelope", 32 байта)
шифртекст = XChaCha20-Poly1305(ключ, nonce 24 Б)
Формат: [версия 2][32 eph][1088 kemCt][24 nonce][шифртекст]. Это тот же подход, что у Signal PQXDH и Apple PQ3: атакующему пришлось бы одновременно взломать X25519 и ML-KEM-768.
Запечатанный отправитель
Снаружи конверта не видно, кто его отправил. Внутри находятся:
- Содержимое (
Payload), подписанное ключом устройства отправителя. - Личность отправителя.
- Сертификат: подпись этой личности над этим устройством.
Так получатель знает, что сообщение пришло от этого человека, и больше никто этого узнать не может.
Группы
Содержимое группового сообщения шифруется один раз случайным ключом. Этот ключ запечатывается (по гибридной схеме) для каждого устройства каждого участника. Каждая копия выглядит как обычное сообщение один на один: ни узлы, ни внешний наблюдатель не могут понять, что это группа и сколько в ней участников.
Дополнение
Перед разделением конверт дополняется до ближайшего фиксированного размера: 2 КБ, 8 КБ, 32 КБ, 128 КБ, 512 КБ, 2 МБ или 8 МБ. «Привет» и короткое голосовое могут весить ровно одинаково. Реальный размер хранится внутри, в зашифрованном виде.
Прямая секретность за счёт смены ключей
Каждое устройство меняет пару X25519 + ML-KEM каждые 24 часа и сообщает новую в своём профиле. Старые пары хранятся 7 дней, чтобы открыть запоздавшие сообщения, а затем удаляются. Даже если сегодня украдут ключ устройства, сообщения старше недели открыть не получится.
Полный тройной храповик (прямая секретность для каждого сообщения) — в планах.
Что защищает аттестация, а что нет
Приложение запрашивает у Apple доказательство (App Attest) того, что это оригинальное, неизменённое приложение на настоящем iPhone. Это защищает сеть от спама и кражи наград. Твои сообщения защищает не она: даже изменённое приложение не сможет прочитать чужие сообщения. Это обеспечивает криптография.
Алгоритмы
| Назначение | Алгоритм |
|---|---|
| Подписи (личность, кошелёк, устройство, узлы) | ed25519 |
| Классическое согласование ключей | X25519 |
| Постквантовая инкапсуляция | ML-KEM-768 (FIPS 203) |
| Вывод ключей | HKDF-SHA512 |
| Аутентифицированное шифрование | XChaCha20-Poly1305 |
| Квитанции | HMAC-SHA512 и SHA-512 |
| Фраза восстановления | BIP-39, 24 слова |
| Идентификаторы транзакций | SHA-256 от канонического JSON |