Ad Nihilum 0.4.3

good-penguin.png

Состоялся релиз Ad Nihilum 0.4.3 — минималистичного сервиса для обмена зашифрованными сообщениями по принципу «прочитал — сжег», ориентированного в первую очередь на self-hosting.

Cервер выступает лишь в роли глухого хранилища. Шифрование и расшифровка происходят исключительно на стороне клиента, в браузере (через AES-GCM).

Особенности

  • локальное зашифрование и расшифрование, сервер никогда не видит ключа;
  • поддержка дополнительного слоя шифрования паролем, о котором (1) не может узнать сервер, (2) нельзя узнать по передаваемой ссылке;
  • проект содержит порядка 2200 строк серверного кода на Си и 600 строк клиентского кода на JS, что упрощает аудит;
  • Ad Nihilum зависит только от libmicrohttpd. Для генерации кодов QR поставляется модифицированная версия QRCode.js;
  • прилагается инструкция по быстрому поднятию локального сервиса без внешнего IP;
  • Ad Nihilum работает и на Android, приложен соответствующий скрипт для сборки в Termux;
  • однопоточный и синхронный сервер.

Изменения

Масштабный редизайн

  • Разделены страницы отправки и получения сообщений, соответствуюзий клиентский код.
  • Вообще дизайн был сильно изменён и скорректирован с учётом пожеланий лорчаню
  • «Простой» и локальный клиенты:
    • добавлен клиент с упрощённым дизайном https://adnihilum.net/simple;
    • клиентские страницы можно сохранить локально и использовать из file://.

Браузерные политики

  • внедрен CSP для борьбы с XSS;
  • сервер шлёт HSTS.

Прочие изменения

  • проект переимнован из Epha-ots;
  • куплен домен adnihilum.net;
  • TLS обеспечивается при помощи Let«s Encrypt, это стоит иметь ввиду (денег нет);
  • упрощена работа с файлами;
  • переход на fat-pointerы;
  • пофикшены мелкие баги;
  • авто-jsminify и сборка клиентских файлов при сборке через CMake.

Обзор протокола

Сгенерировать три случайных значения: ключ K, вектор инициализации N и соль S. K — 256 бит, N — 96 бит, S — 128 бит.

Вывести ID из K и S с помощью HKDF на основе SHA-256.

Сформировать строку дополнительных аутентифицированных данных aad — это просто строка вида: id=ID

Если пользователь задал пароль:

  • вывести Pk из пароля и S с помощью PBKDF2, SHA-256, 800000 итераций;
  • одна и та же соль используется для всего;
  • зашифровать данные с помощью AES-GCM, используя ключ Pk, IV/nonce N и передав aad.

Добавить двухбайтовый тег к уже зашифрованным данным, если пароль был, либо к исходным данным, если пароля не было.

Первый байт имеет значение: он показывает, были ли данные зашифрованы паролем:

  • 0x73 — данные зашифрованы паролем;
  • 0x13 — данные не зашифрованы паролем.

Второй байт — постоянное значение 0x37.

Снова зашифровать результат с помощью AES-GCM, используя тот же iv = N и тот же aad. Это даёт финальный шифротекст ct.

Склеить байты в строку: blob = N .. S .. ct

Отправить blob на сервер вместе с ID. Сервер возвращает blob по этому ID и не может его подменить: клиент сначала проверит ID с использованием N и K ещё до расшифровки, а затем — через aad.

Клиент хранит K. K никогда не отправляется на сервер. Pk тоже не отправляется; всё, что связано с паролем, очищается из памяти.

Клиент формирует ссылку: origin/#ID/K

Здесь ID и K — строки в формате base64url.

Когда получатель открывает ссылку:

  • браузер отбрасывает всё, что начинается с #; это называется location.hash;
  • клиентское приложение загружается с сервера;
  • по моему мнению, это главная дыра: мы фактически снова упираемся в то, что «TLS дырявый»;
  • однако ничто не мешает хранить клиент офлайн;
  • в идеале должен быть отдельный standalone-клиент.

Клиентский JavaScript проверяет location.hash, и если там есть ID и K, он загружает данные с сервера.

Затем он проверяет их, расшифровывает и, если нужно, запрашивает пароль и расшифровывает ещё раз.

Лицензия

Проект распространяется под GPLv3.

>>> Страница проекта на GitHub

>>> Сервис

©  Linux.org.ru