Как проверить, что локальное шифрование в браузере не отправило открытый текст

Стоит ли доверять «локальному шифрованию в браузере», решает не слоган, а то, какие запросы отправила эта операция. Ищите в Network канареечную строку, которая встречается только в этом опыте: в строке запроса, теле и аналитике не должно быть открытого текста, пароля или ключа после #. AES-256-GCM должен отработать в локальном Web Crypto, и только потом шифротекст может уйти наружу.

Сразу вывод: на месте можно сверить, ушли ли в этом HTTP-запросе открытый текст, пароль или ключ из fragment как полезные данные. Это не доказывает, что расширение не читало буфер обмена, и не доказывает, что следующая версия поведёт себя так же. Ниже — повторяемые шаги, а не новый набор прилагательных.

Сначала одним предложением — ответ на запрос

Локальное шифрование в браузере значит, что шифрование и расшифрование происходят во вкладке, которую вы сейчас смотрите: скрипт вызывает Web Crypto API браузера, алгоритмы класса AES-GCM отрабатывают на этом устройстве, а открытый текст и ключи по умолчанию не покидают браузер как тело HTTP. Проверка — не рекламная фраза: откройте DevTools → Network, найдите канареечную строку и при необходимости повторите тест без сети.

Статья для разработчиков, администраторов и всех, кто хочет сам посмотреть, прежде чем отдать файл или пароль «онлайн-инструменту». Она не заменяет инструкцию к файловому шифровальному ящику и не повторяет определение продукта с главной. Главное — проверка, которую можно повторить на любом сайте.

Слоган сам себя не докажет — трафик можно наблюдать

На многих страницах пишут про локальные вычисления, нулевую загрузку и сквозное шифрование. Эти слова могут стоять и на инструменте, который действительно всё считает на этом устройстве, и на странице, которая сначала отправляет исходный текст методом POST, а шифрует уже сервер. У самой фразы нет контрольной суммы.

То, что вы можете увидеть сразу, — метод, адрес, строку query и тело запроса, которые отправила текущая вкладка. Панель Network в Chrome выводит их списком. Если в этих местах появляется имя только что выбранного файла, только что введённая парольная фраза или экспериментальный исходный текст, который знаете только вы, «локальное шифрование» в этом действии не состоялось.

Обратное тоже узко: отсутствие открытого текста в панели значит лишь то, что в наблюдаемых запросах этих полей не было. Это не значит, что в памяти не было открытого текста, и не значит, что расширение браузера не читало поле ввода. Свести рекламу к одному повторяемому наблюдению уже полезно: коллеге можно сказать «я искал канарейку — строка запроса и тело чистые», а не пересылать фразу с официального сайта.

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

Какой слой вычислений имеется в виду под «локально»

«Локально в браузере» — это не «домен выглядит безопасным», а «криптографические операции идут в скриптовом окружении текущего документа». Для AES-256-GCM обычный верный путь — crypto.subtle.encrypt: вывод ключа, шифрование и тег аутентификации идут через собственный интерфейс браузера. На MDN сказано: SubtleCrypto.encrypt доступен только в безопасном контексте; в продакшене это HTTPS. На обычной HTTP-странице crypto.subtle часто оказывается undefined.

AES-GCM выбирают не из-за красивого имени. Это аутентифицированное шифрование с проверкой целостности: если шифротекст изменили или взяли не тот ключ, расшифрование завершится ошибкой, а не выдаст «похоже на мусор, но всё же открытый текст». В параметрах алгоритма IV обычно занимает 12 байт (96 бит) — так рекомендует NIST SP 800-38D для GCM. На каждое шифрование нужен новый случайный IV, тогда один и тот же открытый текст даёт разный шифротекст.

Файловый сценарий можно описать конкретными действиями: вы выбираете файл на этом устройстве, скрипт читает его в память блоками, шифрует по блокам и запускает скачивание шифротекста в браузере. Скачанный .lock или .enc — результат, который собрало это устройство, а не квитанция сервера. Если верхняя граница одного файла записана как 5 GB, речь о потоковой обработке в браузере, а не о том, что удалённый узел принял 5 GB открытого текста.

Ещё нужно отделить «прикладную загрузку» от «запросов, которые страница отправляет сама». Сайт инструментов, которые сразу готовы к работе, всё равно грузит стили, скрипты и шрифты и может отправлять аналитику посещений без тела. Само наличие таких запросов нельзя предъявлять как «файл загрузили». Но если в query или теле аналитики появляется только что введённая парольная фраза, проверяемый пароль или исходный текст до очистки — это уже другое дело.

FastPwd формулирует эту границу так, чтобы её можно было проверить: открытый текст и ключи при генерации паролей, в Проверке пароля, при очистке конфиденциальных данных и при шифровании файлов по умолчанию не покидают браузер; Burn-Link выпускает наружу только шифротекст, а ключ расшифрования лежит во фрагменте URL #. Файловый шифровальный ящик режет файл на блоки по 1 MB и выводит ключ AES-256 из парольной фразы через PBKDF2 (100000 итераций, SHA-256), затем пишет .lock / .enc. Все инструменты открыли — и можно пользоваться, без аккаунта и без хранилища паролей. Обещание всё равно остаётся обещанием. Ниже Network превращает его в чек-лист.

Проверка канарейкой в Network

Сначала подготовьте метку, которой не бывает в настоящей работе. Имя файла может быть canary-fp-20260825.bin, парольная фраза — случайное длинное предложение, в тексте — фраза, которая есть только в этом эксперименте. Канарейка нужна для поиска: вставьте её в фильтр Network; попадание — это провал.

Откройте DevTools, перейдите в Network, включите Preserve log и сначала поставьте фильтр All — не оставляйте сразу только XHR. Отменённый запрос или ответ 4xx уже мог унести открытый текст. Затем выполните действие целиком: выберите файл, введите парольную фразу, нажмите «шифровать» или «сгенерировать». Панель после этого не закрывайте.

  1. Вставьте канареечную строку в фильтр. Красное попадание — остановитесь и читайте этот запрос; к оценке «на ощупь вроде локально» возвращаться не нужно.
  2. Если попаданий нет, по одному откройте Fetch / XHR и сверьте строку запроса, query и тело. Стили, шрифты и скрипты можно не смотреть.
  3. Отдельно отфильтруйте пути аналитики посещений и откройте query и тело. Заголовок страницы и путь могут быть; только что введённой парольной фразы, проверяемого пароля, исходного текста до очистки и содержимого файла быть не должно.

Смотрите строку запроса

Path в полном URL и query после вопросительного знака стоит читать посимвольно. Поля вроде id для поиска записи могут быть; имени файла, парольной фразы, проверяемого пароля и ключа после решётки быть не должно. Сверьте всю строку в адресной строке со строкой запроса: если часть после решётки попала в строку запроса, реализация перепутала fragment с query либо скрипт сам прочитал фрагмент и записал его в запрос.

Смотрите тело запроса

Полезная нагрузка POST / PUT — второе место. Если шифрование файла заявлено как локальное, в теле не должно быть двоичных данных исходного файла и не должно быть парольной фразы. У Burn-Link может быть поле с шифротекстом — это ожидаемые исходящие данные; вам нужно убедиться, что оно не похоже на только что введённый исходный текст. Если страница Проверки пароля уходит POST-ом с проверяемым паролем — хоть «сверить утечки», хоть «посчитать силу» — он уже покинул это устройство.

Отдельно смотрите отправку аналитики

Аналитику посещений часто пропускают. Основной интерфейс чистый, а в отчёте — полный текст из поля ввода: тогда это действие всё равно нельзя считать «открытый текст остался в браузере». Фильтруя пути аналитики, не предполагайте, что «скрипт аналитики безвреден» — это просто ещё один исходящий запрос, и проверяют его так же, как прикладной интерфейс. Аналитика FastPwd идёт через собственный трекер сайта; с localhost по умолчанию ничего не отправляется. Даже так ищите канарейку и убедитесь, что в отчёте нет парольной фразы и содержимого файла.

Включите Preserve log. Если после шифрования страница уходит или перезагружается, а галочка снята, первый запрос с открытым текстом уже могли стереть — и вы получите ложное «панель пустая».

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

Вторая сверка почти ничего не стоит. Дайте странице полностью загрузиться, затем в Network включите Offline — или отключите сеть в системе — и зашифруйте тот небольшой файл, который можно выбросить. Если скачивание .lock всё равно завершается, это шифрование и расшифрование не зависело от живого интерфейса. Это сильный сигнал «локального шифрования в браузере», но не единственный.

Ложные отказы тоже обычны: шрифт или скрипт аналитики краснеют в Offline — это ещё не сбой шифрования. Смотрите, появился ли после кнопки шифрования новый прикладной POST и лежит ли уже результат в папке загрузок. Бывают и ложные успехи: скрипт может сначала положить открытый текст в очередь и отправить его, когда вы снова выйдете в сеть. Поэтому Offline нужно пройти, а уже онлайн — снова искать канарейку.

Вопросительный знак попадает в HTTP; решётка по умолчанию — нет

У URL две части, которые часто смешивают. Query после вопросительного знака входит в строку HTTP-запроса: её видят сервер, обратный прокси и журналы доступа. Фрагмент после решётки браузер по умолчанию оставляет у себя, чтобы его читал скрипт текущей страницы. Цель HTTP-запроса фрагмент не включает — так RFC 9110 описывает request target, и поэтому URL.hash существует только на стороне браузера.

Поэтому если в одноразовой ссылке на шифротекст ключ кладут в #, при открытии s.html?id={id}#{key} сервер по задумке видит только id, а не ключ. Это не отдельный криптопротокол, а поведение браузера для fragment по умолчанию. У него есть граница: вставите полный адрес в тикет, групповой чат или карточку предпросмотра, которая отбрасывает hash, — и ключ из «не входит в HTTP» превращается в «виден на чужом экране и в чужих журналах».

Проверка столь же конкретна: в Burn-Link создайте безвредный тестовый текст и посмотрите, есть ли в теле запроса создания только шифротекст; на странице чтения смотрите, содержат ли URL запроса документа и последующих интерфейсов только id. Содержимое после # в адресной строке не должно появляться в этих запросах. Страница чтения открыта для получателя, вход не нужен.

Куда смотреть Попадает в HTTP? Что считается успехом
Слоган на странице Не участвует Не доказательство, только для сравнения
Строка запроса / query Да Нет канарейки, нет парольной фразы, нет ключа из fragment
POST body Да Нет исходного текста; у Burn-Link допустим только шифротекст
Фрагмент URL # По умолчанию нет Есть в адресной строке, нет в строке запроса
Аналитика посещений Зависит от реализации Нет исходного текста из поля ввода
Шифрование после Offline Нет нового прикладного запроса Шифротекст всё равно скачивается; онлайн снова ищите канарейку

Что вы можете доказать — и чего не можете

Вывод, который поддерживает эта проверка, узкий. Если записать его прямо, пользы больше.

Можно поддержать: в этом браузере, в этой версии и в этом действии открытый текст, парольная фраза и ключ из fragment не покинули вкладку как наблюдаемые прикладные данные HTTP или исходный текст аналитики.

Нельзя поддержать: никакая другая вкладка или расширение не читает буфер обмена; папка загрузок на диске безопасна; получатель не сделает снимок экрана с шифротекстом; Проверка пароля покрыла общесетевую базу утечек. Если проверка считает только локальную энтропию и сверяет с публичным списком слабых паролей Top, она отвечает на «похоже ли это на обычный слабый пароль», а не на «никогда не встречалось в какой-то утечке». Это не общесетевая сверка в стиле HIBP.

Не читайте это и как тест на проникновение. Вы не смотрели WebSocket, кэш Service Worker и не разбирали обфусцированный скрипт. Цель — уметь объяснить коллеге: я открыл Network, искал канарейку, строка запроса и тело чистые. Это ближе к инженерному разговору, чем переслать «на сайте написано, что ничего не загружается».

Частые вопросы

Если шифрование работает без сети, значит ничего не ушло на сервер?

Это доказывает только то, что это шифрование и расшифрование не зависело от живого интерфейса. Скрипты, которые страница уже закэшировала, всё равно могут дослать запросы, когда вы снова выйдете в сеть. Поэтому Offline нужно пройти, а уже онлайн — тем же канареечным маркером снова пройтись по Network. Вывод держится, только если прошли оба шага.

Пустая панель Network значит, что операция безопасна?

Нет. Фильтр только на Img, снятый Preserve log или запрос, стёртый при переходе, дают ложную пустоту. Сначала поставьте фильтр All, затем ищите канарейку и отдельно откройте отчёты аналитики. Пустая панель — это неудавшееся наблюдение, а не доказательство безопасности.

Burn-Link кладёт шифротекст на сервер. Это всё ещё локальное шифрование в браузере?

Это считается «открытый текст посчитали на этом устройстве, наружу ушёл шифротекст». Сервер должен видеть только шифротекст и id для поиска записи; ключ расшифрования стоит в ссылке после решётки и по умолчанию не входит в HTTP. Ни создание, ни чтение не требуют аккаунта. Вам нужно сверить, что в теле не исходный текст и что в строке запроса нет ключа после #.

Отправляет ли проверка пароля вводимый пароль в глобальную базу утечек?

Проверка пароля FastPwd считает силу на этом устройстве и сверяет со встроенным публичным списком слабых паролей. Проверяемый пароль не загружается. Она ловит обычные слабые пароли, но не доказывает «во всей сети не встречалось» и это не сверка в стиле Have I Been Pwned. Возьмите проверяемый пароль как канарейку и поищите в Network — так эту фразу и проверяют.

Те же шаги — на инструменте, который сразу готов к работе

Если хотите потренироваться на странице, где граница вычислений записана явно, начните с файлового шифровального ящика FastPwd. Открыли — и можно пользоваться, регистрация не нужна. Возьмите небольшой файл без настоящих конфиденциальных данных, парольную фразу сделайте канарейкой, зашифруйте и скачайте .lock. Параллельно смотрите Network: статические ресурсы и, возможно, аналитика посещений допустимы; исходный файл и парольная фраза как прикладные поля — нет. Алгоритм — AES-256-GCM, считает Web Crypto, один файл — не больше 5 GB.

Burn-Link удобен для второго упражнения: создайте безвредный тестовый текст и убедитесь, что наружу уходит шифротекст; страница чтения открыта для получателя, форма ссылки — s.html?id={id}#{key}. Очистка конфиденциальных данных годится, чтобы проверить, «попадёт ли исходный текст в аналитику»: ссылки и текст для маскирования по описанию продукта остаются в браузере; достаточно ли результата очистки, решаете вы.

Смысл этих упражнений не в том, чтобы доказать, что какой-то сайт «абсолютно безопасен». Смысл — освоить один и тот же набор шагов. На любой странице, которая заявляет локальное шифрование, шаги те же: канарейка, Preserve log, строка запроса, тело, отправка аналитики и при необходимости ещё раз Offline.

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