Кейс · Бэкенд · TypeScript

Конверт: записки с шифрованием в браузере

Сервис одноразовых записок на TypeScript, Cloudflare Workers и D1: текст шифруется в браузере (AES-256-GCM), ключ лежит только во фрагменте URL и на сервер не попадает. У записки есть срок жизни, пароль и сгорание после первого прочтения. Пет-проект.

  • TypeScript
  • Cloudflare Workers
  • D1
  • Web Crypto
  • Vite
  • vitest
  • fast-check
  • GitHub Actions

01 · Как выглядит

Скриншоты

Скриншот проекта «Конверт: записки с шифрованием в браузере» на экране 1280 пикселей
Десктоп, 1280 px
Скриншот проекта «Конверт: записки с шифрованием в браузере» на экране телефона, 390 пикселей
Телефон, 390 px

02 · О проекте

Что это и зачем

«Конверт» (paste-vault) — сервис одноразовых записок на TypeScript: бэкенд на Cloudflare Workers с базой D1 (SQLite), фронтенд на ванильном TypeScript и Vite без фреймворков. Пет-проект.

Текст шифруется в браузере (AES-256-GCM), ключ генерируется там же и лежит только во фрагменте ссылки после #, поэтому сервер хранит один шифртекст. Для сгорания после прочтения выбран D1, а не KV: чтение и удаление идут одной транзакцией, поэтому записка отдаётся ровно один раз.

Ограничения

Потеряли ссылку с ключом, потеряли записку: восстановления нет. Размер, время создания и число просмотров видны серверу, длина текста не маскируется.

Тест «ровно один успех» гонялся на 40 параллельных чтениях в локальной эмуляции D1 и на 12 параллельных запросах к боевому Worker; это не доказательство для любой нагрузки.

Лимит по IP основан на CF-Connecting-IP: сети с общим адресом упрутся в него раньше, а от распределённого флуда он не защищает. Просроченные записки перестают отдаваться сразу, но физически удаляются cron-задачей раз в 30 минут.

Внешнего аудита нет, это учебный проект.

Что внутри

  • Шифрование на клиенте: случайный 256-битный ключ во фрагменте URL, необязательный пароль через PBKDF2 (600 тыс. итераций) и HKDF; ключ и пароль не уходят на сервер
  • Срок жизни записки от 10 минут до 7 дней, сгорание после первого прочтения, удаление по секретному токену
  • API: метаданные без расхода записки, атомарное чтение (DELETE ... RETURNING одним батчем), cron-очистка просроченных
  • Свой токенайзер подсветки синтаксиса: токены всегда склеиваются обратно в исходный текст
  • Строгий CSP без inline, HSTS, nosniff, проверка Origin, лимит запросов по IP, записки отдаются с noindex и no-store
  • 52 автотеста в рантайме workerd: клиентская криптография, property-тесты fast-check, фаззинг схемы запроса, отсутствие ключа и текста в БД, TTL, права удаления, сгорание под 40 параллельными чтениями
  • Браузерный сценарий по CDP: два независимых профиля, сгорание, пароль, XSS, TTL, axe без нарушений

03 · Как запустить

Запуск одной командой

git clone <репозиторий по запросу> paste-vault
cd paste-vault
npm install
npm run dev   # локальный Worker с эмуляцией D1

04 · Код

Репозиторий приватный

Исходники лежат в приватном репозитории. Напишите в Telegram, открою доступ.

Запросить код