Наблюдаемость криптографической случайности и отпечатки браузера
Сравните Web Crypto getRandomValues и генерацию случайных чисел crypto-js с воспроизводимым fixture и ограниченными наблюдениями приватности.
BotBrowser Team
Нужна структурированная документация по теме Отпечатки?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
BotBrowser может повторить авторизованный fixture одного источника, который записывает доступность API и ограниченные метаданные результата, но не может подтвердить качество энтропии, установить личность или превратить случайное значение в стабильный отпечаток. Полезное сравнение сопоставляет управляемый браузером контракт crypto.getRandomValues() с открытым путём crypto-js, который передаёт случайные байты генератору уровня библиотеки.
TL;DR
crypto.getRandomValues()- API браузера для заполнения типизированного массива; он не раскрывает повторно используемую идентичность браузера.crypto-js- код приложения. Его путь генерации зависит от версии, сборки, глобальных объектов runtime и реально загруженной ветки исходников.- Сравнивайте доступность, версию исходников, форму массива и грубые метаданные. Не публикуйте случайные значения, seed, данные аккаунта или необработанные образцы энтропии.
- Повторный fixture может показать изменившуюся реализацию или сломанный резервная ветка, но один результат не доказывает качество энтропии или уникальность отпечатка.
Contents
- Разделить два источника случайности
- Использовать воспроизводимый fixture
- Диагностика и ограничения
- Читать наблюдения без чрезмерных выводов
- Разделять отпечатки и случайность
- Следующее чтение
- Заключение
Разделить два источника случайности
Спецификация Web Cryptography определяет Crypto.getRandomValues() как операцию браузера над целочисленным типизированным массивом. Справочник MDN описывает поддерживаемые типы массивов, синхронный возврат и ограничение квоты. Браузер владеет базовым источником и может отклонить неверное представление; код страницы не выбирает seed.
У crypto-js другая модель владения. В его открытом дереве исходников есть helper случайных слов для алгоритмов библиотеки, проверки возможностей runtime и резервная ветка, которые менялись между релизами. Прочитайте точный version-tagged исходник, попавший в ваш bundle, и запишите, выбрал ли он браузерный crypto-объект, другого поставщика runtime или резервная ветка. Одного имени пакета недостаточно для вывода о ветке.
Здесь сравниваются наблюдаемые контракты, а не воспроизводится внутренняя энтропия. Fixture может показать наличие crypto.getRandomValues, заполнение типизированного массива и ожидаемую форму результата загруженной сборки crypto-js. Но ни один результат не становится стабильным идентификатором устройства. Для связанной проверки сигналов см. проверку отпечатка браузера и целостность API между realms.
Держите ссылки на исходники рядом с fixture: исходник random crypto-js, релизы crypto-js и согласованность автоматизации BotBrowser. Соответствующая docs-страница описывает проверки согласованности, но не это сравнение уровня исходников и правила редактирования.
Использовать воспроизводимый fixture
Запускайте одну и ту же HTTPS-страницу в новом объявленном профиле. Приведённый fixture записывает только имена веток, длины и короткий digest сгенерированных байтов; само случайное значение не сохраняется.
async function observeRandomness() {
const record = {
fixtureId: 'crypto-randomness-01',
browserCrypto: typeof globalThis.crypto?.getRandomValues === 'function',
cryptoJsLoaded: typeof globalThis.CryptoJS !== 'undefined',
browserLength: null,
libraryLength: null,
digestPrefix: null,
outcome: 'pending',
};
try {
if (record.browserCrypto) {
const bytes = new Uint8Array(32);
globalThis.crypto.getRandomValues(bytes);
record.browserLength = bytes.byteLength;
record.digestPrefix = Array.from(bytes.slice(0, 4), value => value.toString(16).padStart(2, '0')).join('');
}
if (record.cryptoJsLoaded && typeof CryptoJS.lib.WordArray.random === 'function') {
const words = CryptoJS.lib.WordArray.random(16);
record.libraryLength = words.sigBytes;
}
record.outcome = record.browserCrypto || record.cryptoJsLoaded ? 'observed' : 'unsupported';
} catch (error) {
record.outcome = error.name === 'QuotaExceededError' ? 'quota-error' : 'api-error';
}
return record;
}
Fixture воспроизводим, потому что его входы фиксированы: fixtureId, браузерный массив на 32 байта, запрос библиотеки на 16 байт и одна версия загруженного пакета. Результат намеренно недетерминирован. Полезная JSON-передача выглядит так:
{
"fixtureId": "crypto-randomness-01",
"browserCrypto": true,
"cryptoJsLoaded": true,
"browserLength": 32,
"libraryLength": 16,
"digestPrefix": "redacted",
"outcome": "observed"
}
Повторите fixture после изменения одной переменной: сборки браузера, профиля, версии пакета, bundler или runtime. В приватной записи храните browserVersion, os, profile, cryptoJsVersion и testedOn. Не сравнивайте случайные байты; сравнивайте первое изменившееся поле доступности или формы.
| Строка | Одно изменение | Основные поля | Ответственный |
|---|---|---|---|
| A | baseline | все поля fixture | владелец теста |
| B | сборка браузера | browserCrypto, browserLength, outcome | браузер/контекст |
| C | жизненный цикл профиля | доступность и результат | профиль |
| D | версия crypto-js | cryptoJsLoaded, libraryLength, outcome | зависимость |
| E | выход bundler | загрузка и путь метода | сборка |
Диагностика и ограничения
Учитывать лимит Web Crypto в байтах для каждого вызова
Спецификация Web Crypto требует, чтобы getRandomValues() выбрасывал QuotaExceededError, если byteLength типизированного массива превышает 65,536. Проверяйте байты, а не число элементов: Uint32Array(16_384) занимает ровно 65,536 байт, а ещё один элемент превышает лимит. Функция ниже принимает только Uint8Array, где число элементов равно числу байтов; представления с более широкими элементами сначала преобразуйте в байтовое представление:
function fillRandomBytes(output) {
if (!(output instanceof Uint8Array)) {
throw new TypeError('output must be a Uint8Array');
}
const maxBytesPerCall = 65_536;
for (let offset = 0; offset < output.byteLength; offset += maxBytesPerCall) {
const length = Math.min(maxBytesPerCall, output.byteLength - offset);
globalThis.crypto.getRandomValues(output.subarray(offset, offset + length));
}
return output;
}
Это учитывает ограничение размера одного вызова API; больший буфер от этого не становится детерминированным, качество энтропии не проверяется, а случайные байты не становятся пригодными для публикации. Сохраняйте классификацию ошибок из fixture: слишком большой запрос является ошибкой формы запроса, а не свидетельством слабого источника или идентичности браузера.
Если browserCrypto равен false, сначала проверьте origin, realm и контекст. Если изменилось только поле библиотеки, проверьте разрешённый пакет и порядок загрузки. quota-error описывает отклонённый размер, а не слабую энтропию. Не используйте digest-префикс как отпечаток; сохраняйте только ограниченные поля. BotBrowser может повторить авторизованный fixture и сравнить первое изменившееся поле, но не может подтвердить энтропию или идентичность.
Читать наблюдения без чрезмерных выводов
| Наблюдение | Что оно подтверждает | Чего оно не доказывает |
|---|---|---|
browserCrypto: true | страница может вызвать API браузера | качество энтропии, аппаратный источник или личность |
libraryLength: 16 | загруженная библиотека вернула нужную форму | какой поставщик передал байты |
quota-error | браузер отклонил запрошенный размер массива | неисправный профиль или слабую случайность |
изменившаяся ветка cryptoJsVersion | изменение исходников или зависимости для проверки | отпечаток браузера или вердикт безопасности |
Если поле браузера изменилось с true на false, сначала проверьте контекст и изоляцию страницы, а не обвиняйте профиль. Если изменилось только поле библиотеки, проверьте итоговый module entrypoint и порядок инициализации. Повторившийся digest-префикс считайте редактированным артефактом, требующим нового запуска, а не стабильной идентичностью. Рекомендация Web Crypto и исходник crypto-js отвечают на разные вопросы и должны оставаться отдельными ссылками.
Разделять отпечатки и случайность
Отпечаток - набор относительно стабильных или управляемых политикой наблюдений: данные user-agent, параметры экрана или доступность функций. Случайный результат намеренно меняется. Связать случайные образцы с профилем можно на уровне модели данных приложения, но это приложение создаёт идентификатор, а не getRandomValues().
Для минимизированной телеметрии сохраняйте id fixture, ветку API, запрошенные длины, версию пакета, грубый результат и время. Удаляйте случайные значения, seed, полные digest, идентификаторы аккаунтов и межсайтовые связи. BotBrowser может повторить авторизованный fixture и сравнить эти ограниченные поля; он не может сертифицировать сторонний тест энтропии, вывести личность из образца или гарантировать пригодность резервного пути библиотеки для криптографического применения.
Следующее чтение
См. детерминированное поведение и проверку с защитой приватности для разделения повторяемости и минимизации.
| Наблюдение | Назначение | Оставить | Удалить |
|---|---|---|---|
available или error | поддержка совместимости | id fixture и грубое состояние | исходные байты и трассировки |
| длина массива | разбор регрессии | длина и major браузера | полные значения образца |
| digest seeded fixture | проверка повторяемости | ревизия fixture и digest для теста | связь с рабочим аккаунтом |
| число повторов токена | ошибка жизненного цикла | число и интервал истечения | текст токена и URL endpoint |
| резервная ветка | решение продукта | имя ветки и ревизия приложения | данные страницы |
Заключение
Сравнивайте браузерный getRandomValues() с точным открытым исходником crypto-js, который загружает ваш bundle. Используйте фиксированный fixture, сохраняйте только метаданные доступности и формы, а при повторе меняйте одну переменную. Результат объясняет изменение исходников или runtime, но не превращает случайность в отпечаток и не доказывает качество энтропии.
Public sources
Эта статья входит в руководство: Что такое отпечаток браузера?
Похожие статьи
Client Hints Fingerprinting: HTTP-заголовки и идентичность
ОтпечаткиДетерминированный режим: воспроизводимые отпечатки
ОтпечаткиЧто такое отпечаток браузера?
ОтпечаткиОтпечаток Canvas: как он работает и что помогает
ОтпечаткиBattery Status API: приватность и доступность
ОтпечаткиВоспроизводимость шумового зерна для повторяемых запусков
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.