Files
SHiNE-server/docs/Personal_Messages/Технические_вставки_DM_v1.md
T

9.6 KiB
Raw Blame History

Технические вставки внутри plaintext DM v1

Статус документа

Этот файл описывает внутренний формат технических вставок, которые находятся внутри уже расшифрованного plaintext DM.

Важно:

  • это не отдельный серверный DM-envelope;
  • это часть plaintext контентного DM после E2EE-расшифровки;
  • сервер не обязан знать этот формат;
  • клиент может использовать эти вставки для специального UI-рендера.

1. Общий принцип

Обычное сообщение по-прежнему остаётся обычным текстом.

Если в начале plaintext стоит один или несколько специальных блоков формата:

<S:...>

то клиент трактует их как технические вставки.

Техническими считаются только блоки, которые:

  • стоят строго в начале plaintext;
  • начинаются с префикса <S: или legacy-префикса <SHiNE:;
  • заканчиваются первым символом >.

Если текст не начинается с <S: или <SHiNE:, никакие технические вставки не ищутся.

2. Правило скрытия

Все корректно распознанные блоки <S:...> или <SHiNE:...> в начале plaintext:

  • не показываются пользователю как сырой текст;
  • используются клиентом для UI-логики;
  • неизвестные будущие типы тоже скрываются, если они распознаны как корректный SHiNE-блок.

Если блок битый и не закрыт символом >, он не считается техническим и сообщение показывается как обычный текст целиком.

3. Защита от случайного пользовательского ввода

Перед отправкой обычного текстового сообщения клиент обязан проверить:

  • если пользовательский текст начинается с <S: или <SHiNE:

то клиент автоматически превращает начало в:

< SHiNE:

Такой текст уже не считается техническим блоком и должен отображаться как обычное сообщение.

4. Формат блока

Общий вид:

<S:kind;key=value;key=value;...>

Правила:

  • kind — ASCII-идентификатор типа вставки;
  • параметры отделяются ;;
  • ключ и значение отделяются =;
  • значения обычных v1-вставок не экранируются; для file поля url, name, mime кодируются через percent-encoding (encodeURIComponent), чтобы ;, = и > внутри метаданных не ломали блок;
  • канонический новый префикс: <S:;
  • legacy-префикс <SHiNE: продолжает поддерживаться при чтении.

5. Тип reply

Формат:

<S:reply;v=1;id=user1|user2|1720612345678|77>Текст ответа

Где поле id — это логический идентификатор сообщения:

fromLogin|toLogin|timeMs|nonce

Правила:

  • этот блок должен стоять в начале plaintext;
  • после него может идти обычный текст ответа;
  • официальный UI формирует такой блок при отправке ответа через пункт Ответить в меню сообщения;
  • если клиент не находит сообщение, на которое ссылается reply, он просто не показывает reply-preview;
  • в таком случае само сообщение отображается как обычный текст без блока <S:reply...>.

6. Тип call

Успешный звонок

<S:call;v=1;status=completed;duration=367>

Где:

  • duration — длительность разговора в секундах.

Неуспешный звонок

<S:call;v=1;status=failed;reason=offline>

Допустимые причины в v1:

  • offline
  • no_answer
  • connect_failed
  • busy
  • declined

Правила:

  • call-блок в v1 должен содержать только техническую запись звонка;
  • пользовательский текст после такого блока в штатной логике не предполагается;
  • UI может рисовать такие сообщения отдельным специальным стилем.
  • официальный UI не отправляет call-summary, если от старта исходящего звонка до его завершения прошло меньше 5 секунд.

7. Тип file

Формат v1:

<S:file;v=1;id=BASE58_SHA256;url=ENCODED_URL;key=BASE64URL_AES_KEY;iv=BASE64URL_IV;name=ENCODED_NAME;mime=ENCODED_MIME;size=123;encsize=139>📎 example.pdf

Поля:

  • idBase58(SHA-256(ciphertext));
  • url — абсолютный URL ciphertext на access-сервере отправителя, percent-encoded;
  • key — случайный 32-byte AES-256 key в Base64URL;
  • iv — случайный 12-byte AES-GCM IV в Base64URL;
  • name — исходное безопасно нормализованное имя файла, percent-encoded;
  • mime — исходный MIME, percent-encoded;
  • size — размер plaintext в байтах;
  • encsize — размер ciphertext в байтах.

key, iv и метаданные безопасно находятся здесь только потому, что весь plaintext DM затем шифруется существующим E2EE-механизмом. Они не передаются файловому HTTP endpoint отдельно.

Текст 📎 example.pdf после блока служит fallback для старого клиента. Новый официальный UI вместо него рисует карточку файла и кнопку «Скачать».

Перед локальной AES-GCM-расшифровкой клиент обязан повторно вычислить SHA-256 скачанного ciphertext и сравнить Base58 с id.

8. Поведение официального UI

Официальный UI SHiNE в v1:

  • скрывает все корректные <S:...> и legacy <SHiNE:...> блоки в начале plaintext;
  • для call строит специальный человекочитаемый текст:
    • Звонок: M:SS
    • Звонок: H:MM:SS
    • Звонил, но недозвонился: ...
  • для reply скрывает сам блок и показывает только текст ответа;
  • для file скрывает fallback-текст и показывает карточку вложения с локальным download/decrypt;
  • если исходное reply-сообщение не найдено, reply-preview не показывается.

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

Так как это часть plaintext, а не часть серверного envelope:

  • сервер не обязан понимать этот формат;
  • будущие клиенты могут добавлять новые kind;
  • клиенты, которые распознают SHiNE-вставки, должны скрывать неизвестные блоки целиком, если они стоят в начале и корректно закрыты.

10. Расширение file v2

Клиент обязан продолжать читать v=1. Новые chunked-вложения отправляются так:

<S:file;v=2;id=ROOT_MANIFEST_ID;url=ENCODED_URL;key=BASE64URL_AES_KEY;ivp=BASE64URL_4BYTE_PREFIX;name=ENCODED_NAME;mime=ENCODED_MIME;size=123;encsize=456;chunk=1048576;chunks=7;th=TORRENT_V2_INFOHASH;pr=TORRENT_V2_PIECES_ROOT;kind=file;dur=0>

Дополнительные поля v2:

  • id / url указывают не на весь файл, а на зашифрованный root manifest;
  • ivp — случайный 4-byte IV prefix, из которого детерминированно строятся уникальные IV chunks/pages/root;
  • chunk — plaintext chunk size, сейчас 1048576;
  • chunks — число частей;
  • th — BitTorrent v2 SHA-256 infohash;
  • pr — BitTorrent v2 pieces root;
  • kind=file|voice;
  • dur — длительность voice в миллисекундах, для обычного файла 0.

В одном plaintext DM разрешено несколько последовательных <S:file...> блоков. Официальный UI собирает их в один список вложений и скрывает fallback-текст.

Подробный формат chunk encryption, manifest pages и BitTorrent v2 hashing: Файлы_DM_v2.md.