Безопасность в qub

Дата вступления в силу: 23 сентября 2026 Версия: 1.1 — обзор точности реализации


Для исследователей — быстрая справка:

Полные сведения содержатся в §12 (Координированное раскрытие).


Кто мы такие

qub.social управляется VSPRY AUSTRALIA PTY LIMITED (ABN 41 631 026 330), Level 38, 71 Eagle Street, Brisbane QLD 4000, Australia. Упоминания «qub», «мы», «нас» и «наш» означают данное юридическое лицо.

Контакт по безопасности: support@qub.social с префиксом темы [SECURITY].


1. Наш подход

qub — это инфраструктура доверия. Продукт не имеет ценности, если он небезопасен, поэтому безопасность — это не функция, а субстрат. Эта страница описывает в конкретных терминах, как мы защищаем наш стек, Ваши данные и целостность запечатанного контента.

Ценность проверяемого временного обязательства растет по мере того, как все больше интернета становится сгенерированным машинами. Проверенная транзакция хранения или якорь журнала прозрачности могут установить, что шифротекст существовал не позднее своего времени блока; запечатанный артефакт отдельно подтверждает целостность содержимого, привязку к раунду drand и любые подписи авторства. Сохранение этих утверждений отдельно — это стандарт, которому соответствует эта страница.

Мы не просим Вас доверять нам. Мы проектируем так, чтобы требуемое от нас доверие было настолько малым, насколько это возможно, и там, где доверие требуется, мы точно объясняем, чему именно доверяют и почему.

Три принципа определяют каждое проектное решение:


2. Модель угроз

2.1 От чего мы защищаем

2.2 От чего мы не можем защитить

Мы честны в отношении наших пределов. qub не может защищать от:


3. Криптография на стороне клиента

В стандартном потоке сообщений браузера шифрование содержимого происходит до запроса на загрузку. Существуют два явных пути, которые различаются: Builder /api/v1/seal намеренно отправляет открытый текст и ключ K, сгенерированный вызывающим, Работнику для защиты в памяти, а постановка/со-подпись пакта отправляет подписанный структурированный пакт в службу, чтобы она могла завершить двусторонний артефакт. Ни одно из исключений не следует ошибочно принимать за сквозное шифрование через браузерный путь.

3.1 Timelock-шифрование

qub использует tlock — основанное на идентичности шифрование, привязанное к будущему раунду маяка drand. Шифрование выполняется в Вашем браузере с использованием публичного ключа сети drand; ключ расшифровки публично выпускается сетью drand только тогда, когда достигается целевой раунд. Никто, включая нас, не может реконструировать ключ расшифровки заранее.

Мы нацеливаемся на цепочку quicknet:

Публичный ключ и время genesis цепочки quicknet вкомпилированы в клиент. Мы не запрашиваем параметры цепочки во время выполнения, поэтому вредоносный узел не может подставить цепочку, которую мы контролируем.

3.2 Симметричное шифрование

Схема tlock оборачивает контентный ключ AES-256-GCM. AES-GCM обеспечивает аутентифицированное шифрование: один перевёрнутый бит в шифротексте приводит к сбою расшифровки, а не к молча испорченному открытому тексту.

3.3 Каноническая сериализация

Структуры протокола сериализуются с использованием детерминированного CBOR (RFC 8949 §4.2 основное детерминированное кодирование). Две реализации, кодирующие одну и ту же логическую структуру, производят идентичный CBOR. Полные запечатанные полезные нагрузки являются не детерминированный: tlock и шифрование внешней оболочки используют свежие случайные значения. Хеш тела вычисляется по необработанным байтам тела, в то время как каноническое кодирование делает окружающие подписанные/сетевые структуры однозначными.

Мы написали CBOR-кодировщик вручную как для нашей клиентской, так и для серверной реализации, не полагаясь на общую библиотеку сериализации — требование — точность, а не эргономика, и property-тесты выполняются в обеих реализациях, чтобы убедиться, что они согласуются.

Регрессионный тест утверждает, что канонический wire-формат не содержит ни одной байтовой последовательности бренда qub за пределами ключа поля протокольного примитива qub_id. Wire-формат намеренно бренд-нейтрален — любой соответствующий просмотровщик (наш или сторонний) может отрендерить любой qub из постоянного хранилища, независимо от того, какое развёртывание его запечатало. Тест — это растяжка, которая предотвращает то, чтобы будущее изменение случайно вбило ссылку на бренд в байты, которые, оказавшись в постоянном хранилище, уже не могут быть переписаны.

3.4 Хеширование тела и pre-reveal целостность

Каждая запечатанная полезная нагрузка содержит хеш SHA3-256 от своих необработанных байтов тела. Хеш связан с qub_id и, когда включена подпись авторства, в поле ввода подписи V2. Просмотрщик пересчитывает её после расшифровки и отклоняет несоответствие.

32-байтовый идентификатор содержимого qub_id получается из предобразца размером 108 байт, охватывающего версию протокола, тип содержания, временные метки создания и разблокировки, необязательную временную метку исхода (или её нулевой сигнал), целевой раунд drand, хеш тела и SHA3-256 необязательного нормализованного по NFC заголовка. Шлюз или CDN не могут изменить какое-либо связанное поле последовательно и при этом пройти повторное вычисление. Заголовки ограничены 100 NFC-кодовыми точками и отклоняются для общего класса враждебных/контрольных кодовых точек (включая переопределения bidi, символы с нулевой шириной, блок тегов, BOM, C0, C1 и DEL).

3.5 Подписание (ML-DSA-65)

Подписание авторства использует ML-DSA-65 (FIPS 204), стандартизованную NIST постквантовую схему подписи. Мы сознательно выбрали постквантовый примитив для подписания, потому что запечатанный контент постоянен: подпись, которая проверяется сегодня, должна продолжать проверяться через десятилетия, в том числе после того, как крупномасштабные квантовые компьютеры станут практичными.

Ключи для подписания генерируются в браузере. Локальный секрет оборачивается в невынимаемый ключ WebCrypto перед сохранением в IndexedDB. Если используется функция восстановления между устройствами в рамках учетной записи, зашифрованный AEAD портативный ключ сохраняется на стороне сервера; его шифротекст секретного ключа привязан к неизменяемому идентификатору учетной записи, и сервис проверяет публичный конверт, но не может расшифровать секретный материал. Сырые байты приватного ключа не отправляются на сервер. Публичные ключи и записи аттестации сохраняются для проверки и отображения идентичности.

То же in-browser tlock-расшифрование применяется внутри эмбеда qub: когда запечатанный qub рендерится через <qub-embed> на сторонней странице, расшифрование по-прежнему происходит в iframe эмбеда в браузере зрителя. Эмбед не меняет модель доверия — открытый текст никогда не расшифровывается на сервере qub.

3.6 Публичная атрибуция — Opt-In

Запечатанные qubs не несут on-chain-указателя на их создателя, если только создатель явно не выберет прикрепить его. Когда Вы запечатываете qub, эталонное приложение выпускает тег хранилища Author (64-символьный hex-«отпечаток» Вашего подписного публичного ключа) только тогда, когда «Публичная атрибуция» включена на шаге выбора даты. С выключенным переключателем — по умолчанию — никакой Author-тег не пишется, и qub не атрибутирован в постоянном хранилище: ничто в хранилище не связывает загрузку с Вашим handle, Вашим email или Вашими другими qubs. С включённым переключателем «отпечаток» разрешается в Ваш @handle через цепочку аттестаций в §6.3 / §10, и обратный отсчёт у зрителя показывает «Запечатано @{handle}» до раскрытия.

Это намеренная защита от риска перечисления, который создал бы постоянно включённый Author-тег: третья сторона, узнавшая «отпечаток» создателя, могла бы иначе обыскать постоянное хранилище по тегу и реконструировать всю историческую активность этого создателя. Opt-in-атрибуция закрывает этот канал — только те qubs, которые создатель явно выбирает атрибутировать, появляются под «отпечатком» в постоянном хранилище.

Страница профиля /u/{handle} — это карточка подтверждённой идентичности — handle, опциональное отображаемое имя + URL, значок «verified email» (без адреса) и короткая форма криптографического «отпечатка». Она не перечисляет qubs создателя. Посетители, которые хотят увидеть конкретный qub от создателя, переходят по URL доставки этого qub напрямую.

3.7 Внешняя обёртка шифрования

Даже после того, как расшифровка с таймлоком становится математически возможной — как только подпись drand для привязанного раунда будет опубликована — только канонический слой таймлока позволил бы индексеру массово расшифровывать обнаруживаемые квабы. Частная доставка закрывает этот канал с помощью дополнительного симметричного слоя вокруг байтов, зашифрованных таймлоком (Протокол §13). Публичная доставка намеренно опускает этот обертку, чтобы уведомления, встраивания и ссылки на обнаружение могли работать без секретного фрагмента.

Обёртка использует AES-256-GCM, стандартизованный NIST аутентифицированный шифр, со свежим 256-битным ключом K, генерируемым для каждого qub браузерным CSPRNG. K связан с qub_id qub как аутентифицированные дополнительные данные, поэтому ключ от одного qub нельзя переиспользовать для расшифрования другого qub.

K никогда не достигает наших серверов в стандартном режиме приватного браузера. Он закодирован в фрагменте URL общей ссылки (https://qub.social/c/<tx_id>#<base64url(K)>). Браузеры не передают фрагменты URL на серверы — RFC 3986 помещает фрагмент вне запроса — поэтому qub.social, шлюзы хранения, CDN и мониторинг запросов не видят K в этом потоке. Сохраненный OuterWrapper это распознаваемый структурированный CBOR, но его поле аутентифицированного шифротекста скрывает внутреннее SealedQub структура и не может быть открыта без K.

Чистые последствия:

Серверный эндпоинт Worker /api/v1/seal (используемый ИИ-агентами и другими вызывающими API) требует, чтобы вызывающий сгенерировал K с помощью CSPRNG, сохранил его локально и передал в виде wrapper_key_b64url. Worker неизбежно видит в памяти и открытый текст, и K на этом явно доверенном пути, но не сохраняет ни того, ни другого. Обязательный Idempotency-Key не позволяет потерянному ответу создать второй тарифицируемый qub, а сохранённый вызывающим K можно объединить с воспроизведённым URL без фрагмента. Это отличается от пути браузера по умолчанию, где K никогда не достигает Worker, если только автор явно не включит восстановление.


4. Транспорт и edge

4.1 TLS

Трафик браузера к qub обслуживается через HTTPS на стороне Cloudflare. Ответы устанавливают строгую политику транспортного уровня HTTP (HTTP Strict Transport Security) (max-age=63072000; includeSubDomains; preload). Точная согласованная версия TLS и набор шифров управляются активной конфигурацией периферийного узла, а не задаются кодом приложения. Мы не предоставляем отдельно доступный исходный сервер.

4.2 Безопасность контента

Скомпилированный клиент обслуживается со строгими заголовками content-type и кеша. SPA-оболочка — единственный origin. Мы не встраиваем сторонние скрипты для аналитики или рекламы. Две сторонние точки касания в продукте обе узко ограничены: поток покупки полностью покидает SPA полностраничным редиректом на размещённый Stripe checkout (https://checkout.stripe.com/…) — UI Stripe никогда не выполняется в нашем origin, и мы никогда не видим данные карты — и поток запечатывания загружает виджет Cloudflare Turnstile, альтернативу CAPTCHA, сохраняющую приватность, который Cloudflare рендерит внутри собственного iframe-песочницы. Ни одна сторона не может прочитать остальную часть страницы.

Этот qub встроить iframe (обслуживается с qub.social/embed/{tx_id} и загружены на сайты третьих лиц embed.js) имеет свою собственную Политику безопасности контента. Его connect-src белый список это 'self', https://qub.social, https://arweave.net, https://ar-io.dev, https://permagate.io, https://api.drand.sh, и https://drand.cloudflare.com. Iframe работает с sandbox="allow-scripts allow-top-navigation-by-user-activation" (не allow-same-origin): главная страница не может читать свой DOM и не может перемещаться по хосту, кроме как после действия пользователя.

4.3 CORS и охват fetch

Браузерный клиент делает fetch-запросы только к:

Назначения встроенного объекта определяются его CSP. Назначения основного SPA заданы в коде и конфигурации и проверяются браузером и средствами интеграции; целостность подресурсов не является механизмом контроля назначения в сети.

Встраиваемый элемент извлекает сохраненные байты через разрешенные источники qub/storage, распаковывает приватные полезные нагрузки в браузере с использованием K из фрагмента URL и получает подписи раундов времени раскрытия с двух разрешенных источников drand. Основное SPA использует набор резервных конечных точек из четырех элементов, установленный в config/drand-endpoints.json (drand.cloudflare.com, api.drand.sh, api2.drand.sh, и api3.drand.sh) поэтому сбой одной конечной точки не блокирует раскрытие. Встроенный CSP запрещает подключения вне его явного списка.


5. Серверная инфраструктура

5.1 Бессерверный edge

Наш API работает полностью на управляемой бессерверной среде выполнения на edge. Нет ни VM, ни контейнеров, ни постоянных серверных процессов, которыми мы администрируем. Это резко сокращает поверхность атаки, за которую мы отвечаем: мы не запускаем ОС, веб-сервер или среду выполнения приложения, которые мы должны патчить.

Применяется отдельное промежуточное ПО public-CORS Access-Control-Allow-Origin: * к следующему заданному пути: /embed.js, /embed/v1.js, всё под /embed/; /api/v1/telemetry; /api/v1/openapi.json; всё под /api/v1/qub/ (включая подпути bytes, metadata, proof, engagement, notify и push); всё, что находится под /api/v1/log/; общедоступные поиска обработчиков в рамках /api/v1/handle/; и публичный аватар читает ниже /api/v1/identity/avatar/. Его разрешения на предполетную проверку GET, POST, и OPTIONS с Content-Type заголовок запроса. Этот поверхностный слой на основе префикса шире, чем только вызовы, которые встраивание делает в данный момент, поэтому каждый обработчик ниже этих префиксов должен продолжать обеспечивать собственную проверку, аутентификацию, ограничения по скорости и меры против злоупотреблений. Другие пути API сохраняют политику CORS, ограниченную qub.social.

5.2 Хранилище

Поток сообщений браузера по умолчанию не сохраняет открытый текст на инфраструктуре qub. Builder /api/v1/seal обрабатывает открытый текст и K в памяти, но не сохраняет ни то, ни другое. Этап подготовки Pact обязательно сохраняет подписанный структурированный pact до тех пор, пока он не будет подписан совместно, отозван или не истечет. Включенное по желанию восстановление сохраняет возможность доставки (полную ссылку с фрагментом), чтобы ее можно было восстановить позднее. Поэтому мы не описываем весь уровень хранения как «только метаданные».

5.3 Секреты

Секреты (подпись кошельков, токены провайдера и ключи HMAC) предоставляются через привязки секретов/окружения платформы, а не через систему контроля версий. Компоненты во время выполнения получают только те привязки, которые им необходимы. Процедуры ротации и наложения зависят от конкретного компонента; мы не заявляем о существовании единого универсального автоматического или аудируемого механизма ротации.

5.4 Логирование и телеметрия

Структурированные JSON-логи пишутся при каждом API-запросе с correlation ID, выводимым в заголовке ответа X-Request-Id. Клиентская телеметрия анонимна — никакого идентификатора устройства, никакого IP-адреса, никакого превью контента. События буферизуются в памяти и сбрасываются на best-effort-основе; неудачный сброс отбрасывается, не повторяется. Телеметрия спроектирована так, чтобы её можно было отключить на сетевом уровне без влияния на продукт.


6. Аутентификация

6.1 Magic-link вход

Вход выполняется с использованием одноразового токена, подписанного HMAC, который доставляется на вашу электронную почту. Ссылка действительна в течение 15 минут, и использование токена производится атомарно, поэтому одновременное или повторное использование не допускается. В случае успеха браузер получает непрозрачный __Host-qub_session печенье с Secure, HttpOnly, SameSite=Strict, и Path=/ атрибуты.

Сессии имеют 30-дневный лимит бездействия и 90-дневный абсолютный лимит, обновляются каждые 24 часа и принимают только предыдущую генерацию в течение 120 секунд после потери ответа. Для чувствительных изменений аккаунта требуется аутентификация в течение последних 10 минут. Секрет подписи HMAC привязан к платформе; только чтение метаданных само по себе не создает действительный токен.

6.2 API-ключи (тариф разработчика)

API-ключи разработчика используют префикс qub_sk_ для лёгкого распознавания и поиска по grep. Каждый ключ:

Административные эндпоинты управления ключами защищены отдельными административными учётными данными.

6.3 Email-аттестация (подписание авторства)

Привязка email-адреса к подписному ключу требует:

  1. Обладания приватным подписным ключом (Вы подписываете challenge)
  2. Обладания почтовым ящиком email (Вы вводите 6-значный код, доставленный email)

Любого из них в отдельности недостаточно. Отзыв — это подписанная запись в Вашем собственном аккаунте и вступает в силу немедленно; просмотровщики, извлекающие аттестацию, видят отозванное состояние и отображают соответствующим образом.


7. Платежи

Ввод и обработка карты выполняются внутри оформленного в Stripe процесса оплаты. Мы никогда не получаем номера карт, даты истечения срока действия или CVC. Мы сохраняем идентификаторы клиентов и подписок Stripe, состояние подписки и данные о периоде в записях прав/ключей API, чтобы можно было согласовать доступ, продления, измерение использования, отмену и возвраты. Политики конфиденциальности и безопасности Stripe регулируют обработку платёжных данных.

Эндпоинт запечатывания перекрёстно проверяет запись права относительно идентификатора устройства и, для авторизованных пользователей, относительно привязанной идентичности. Право не может быть переиспользовано между устройствами без явного восстановления пользователем через magic-link вход.


8. Устойчивость к злоупотреблениям

8.1 Обнаружение ботов

Поток запечатывания защищён альтернативой CAPTCHA, сохраняющей приватность, которая не использует cookies для отслеживания и не делает «отпечаток» для рекламы. Неудачный challenge отвергается нашим edge Worker до того, как произойдёт какая-либо обработка на стороне запечатывания.

8.2 Ограничение скорости

Ограничения скорости применяются на нескольких слоях:

Счётчики и атомарные операции распределяются между KV, Durable Objects и привязками платформенного ограничения скорости в соответствии с требованиями консистентности конечной точки. Запросы с ограничением скорости возвращают 429; конечные точки, которые могут вычислять окно повторной попытки, включают Retry-After.

8.3 Модерация контента

Маршрут загрузки через браузер по умолчанию не может сканировать тело: он получает только клиентский зашифрованный артефакт. Строитель /api/v1/seal маршрут временно видит открытый текст, а этап подготовки пакта хранит структурированные условия до его завершения, но эти исключения доверия не превращают общий путь загрузки байтов, слепой к содержимому, в сканер содержимого. Оперативная модерация является черный список на уровне просмотровщика: упомянутый в черном списке qub отклоняется нашим просмотровщиком независимо от того, остаётся ли доступным сохранённый полезный нагрузочный поток. Внесение в черный список не отменяет надёжные байты, записи в журнале прозрачности или данные постоянной сети, которые уже были опубликованы.

Жалобы на злоупотребления ограничиваются по скорости с использованием одностороннего хеша IP заявителя; мы не храним IP в открытом виде для этой цели.


9. Цепочка поставок и целостность сборки

9.1 Закрепление цепочки инструментов

Версии компилятора и среды выполнения зафиксированы в конфигурации репозитория, а зависимости разрешаются через зафиксированные lock-файлы. CI проверяет актуальность сгенерированных файлов и инварианты, чувствительные к воспроизводимости. Мы не делаем более сильного утверждения, что каждая чистая сборка идентична бит в бит на всех поддерживаемых машинах.

9.2 Линты и статический анализ

Workspace включает наши строжайшие группы линтов на уровне deny. CI рассматривает каждое предупреждение — включая предупреждения о ссылках в документации — как сбой сборки. Это сознательно: мы используем строгость линтов как растяжку для тонких регрессий.

9.3 Шлюзы CI

CI-воркфлоу охватывает форматирование и строгие линтеры; тесты Rust, WASM/браузер, Worker, embed и API; проверку типов; покрытие кода; проверки мутаций/инвариантов; статический анализ зависимостей и воркфлоу; проверки ключей i18n, покрытия, дрейфа и вредоносных кодовых точек; свежесть сгенерированной документации/API/базы знаний; проверку инвентаря документов и внутренних ссылок; бюджеты стилей и сборок; и валидацию OpenAPI. Некоторые ресурсоёмкие задания по мутациям планируются, а не выполняются при каждом пуше.

Один обязательный ci сводка остаётся красной, если любая необходимая задача не выполнена. Рабочие процессы защищённой ветки и развертывания используют этот результат, а не дублируют меньший этап проверки безопасности.

9.4 Mutation testing

Еженедельная задача запускает mutation testing против security-критичных чистых модулей: хеширования, канонического CBOR, seal, unlock, wire-format newtypes, валидаторов типов протокола и handle-namespace. Mutation testing отвечает на «улавливает ли наш набор тестов тонко неправильный код?» — если мутированная реализация всё равно проходит все тесты, мы знаем, что у нас есть пробел в покрытии тестами, и устраняем его.

9.5 Git hooks

Локальные хуки (pre-commit, pre-push) зеркалят шлюзы CI, так что регрессии ловятся до того, как покинут машину разработчика. Хуки устанавливаются через скрипт репозитория; они не обходятся в нашем рабочем процессе, а CI является авторитетным шлюзом, если их пропустить.


10. Тестирование

Security-критичный код несёт три вида тестов:


11. Гигиена веток и релизов

Фичевые ветки продвигаются staging только через запрос на вытягивание Gate 1: обязательно ci зелёный, нет нерешённых запросов на изменения, нет конфликтов слияния и чистое проверенное дерево; слияние выполняется с объединением и удалением. main продвигается только через Ворота 2 staging → main pull request и сохраняет родословную с помощью коммита слияния. Прямые push на ветку не являются рабочим процессом выпуска.

Развертывание на промежуточной и боевой средах запускается из соответствующей защищённой staging и main ветки состояния после CI. Код pull-request и учетные данные форка не получают секреты развертывания.

Секреты, используемые в деплой-воркфлоу, ограничены окружением деплоя нашей CI-платформой. Они не доступны воркфлоу pull-request из форков.


12. Координированное раскрытие

Если Вы полагаете, что нашли уязвимость безопасности в qub, мы хотим узнать об этом быстро и обязуемся профессионально обработать отчёт.

Мы подтверждаем получение в течение трёх рабочих дней и держим Вас в курсе хода нашего расследования. С Вашего согласия мы упоминаем заявителей в release notes.

12.1 Safe Harbor

Если Ваше исследование следует приведённым выше правилам (добросовестное исследование, никакого вреда другим пользователям или сервису, разумное окно раскрытия), мы не будем предпринимать против Вас юридических действий и не будем просить об этом правоохранительные органы. Мы рассматриваем Вашу работу как уполномоченное тестирование, и мы предпочли бы, чтобы баг нашли Вы, а не кто-то ещё.

Этот Safe Harbor применяется к:

Он не применяется к социальной инженерии членов команды qub, тестам отказа в обслуживании или доступу к данным других пользователей сверх того, что необходимо для демонстрации проблемы. Если Вы не уверены, попадает ли что-то под Safe Harbor, спросите заранее с тем же префиксом темы [SECURITY].


13. Честные ограничения

Безопасность — это практика, а не состояние. Некоторые ограничения стоит назвать прямо:


14. Изменения настоящей страницы

Существенные изменения отмечаются обновлением даты вступления в силу в верхней части. Где изменение отражает конкретное улучшение безопасности, мы кратко описываем его в публичном changelog. Где изменение отражает уточнение политики, мы описываем, что изменилось и почему.

По вопросам о чём-либо на этой странице напишите на support@qub.social с префиксом темы [SECURITY].


15. Журнал изменений

Версия Дата вступления в силу Резюме
1.1 23 сентября 2026 Согласованы криптографические утверждения, режимы доставки, хранение, CSP, сессии, API-ключи, платежи, CI и процесс выпуска с реализованной системой.
1.0 2 мая 2026 Первоначальная публикация.