Назад в Центр знаний
Отпечатки

Наблюдаемость криптографической случайности и отпечатки браузера

Сравните 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

Поток отделяет WEB_CRYPTO и CRYPTO_JS от ограниченной записи и границы приватности.

Разделить два источника случайности

Спецификация 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. Не сравнивайте случайные байты; сравнивайте первое изменившееся поле доступности или формы.

СтрокаОдно изменениеОсновные поляОтветственный
Abaselineвсе поля fixtureвладелец теста
Bсборка браузераbrowserCrypto, browserLength, outcomeбраузер/контекст
Cжизненный цикл профилядоступность и результатпрофиль
Dверсия crypto-jscryptoJsLoaded, 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

#Web Crypto#getRandomValues#Crypto-Js#Browser Fingerprints#Randomness

Эта статья входит в руководство: Что такое отпечаток браузера?

Переведите BotBrowser из исследований в продакшн

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