WebGL Pixel Hash: хеш пикселей GPU как идентификатор
Браузер и устройство

WebGL Pixel Hash: хеш пикселей GPU как идентификатор

WebGL Pixel Hash — это хеш буфера пикселей GPU из gl.readPixels() — стабильный идентификатор устройства, основанный на особенностях рендеринга видеокарты.

8 мин чтения·

WebGL Pixel Hash fingerprinting рендерит невидимую тестовую сцену с помощью GLSL-шейдера и считывает полученные пиксели через gl.readPixels() — эксплуатируя тот факт, что каждый GPU вычисляет арифметику с плавающей точкой немного по-разному, создавая стабильный хеш, идентифицирующий оборудование во всех браузерах, переживающий очистку cookies и не поддающийся скрытию через VPN. Посмотрите свой WebGL pixel hash прямо сейчас на whatsmy.fyi.

TL;DR

Программа GLSL-шейдера компилируется и выполняется на GPU в скрытом WebGL canvas. Отрендеренные значения пикселей считываются обратно и хешируются в компактный идентификатор. Поскольку округление с плавающей точкой в шейдерных блоках GPU варьируется между производителями, архитектурами и версиями драйверов, один и тот же шейдер даёт немного разные пиксельные выводы на разном оборудовании — даже на двух машинах с одинаковой моделью GPU, но разными версиями драйверов. Это делает хеш пикселей более точным идентификатором, чем простое считывание строки рендерера GPU.

Что такое WebGL Pixel Hash Fingerprinting?

WebGL pixel hash fingerprinting — специфическая техника в более широком семействе WebGL fingerprinting, нацеленная на вычислительный вывод GPU, а не его метаданные. Считывание строки рендерера GPU через WEBGL_debug_renderer_info сообщает трекеру модель GPU, но не может различить два идентичных GPU с разными версиями драйверов. Хеш пикселей закрывает этот пробел.

Техника работает, потому что WebGL API даёт JavaScript прямой доступ к выполнению шейдеров GPU. Скрипт fingerprinting может выполнять математически точные вычисления с плавающей точкой на GPU и считывать результаты обратно в виде пиксельного буфера.

Как работает WebGL Pixel Hash?

Шаг 1 — Компиляция шейдера

Скрипт создаёт WebGL canvas и компилирует пару GLSL-шейдеров — вершинный и фрагментный. Фрагментный шейдер выполняет намеренно сложные математические операции с плавающей точкой: тригонометрию, экспоненты, нормализацию векторов. Именно эти операции производят специфичные для оборудования вариации в результатах.

Шаг 2 — Выполнение на GPU

WebGL вызов рисует геометрию (обычно простой прямоугольник) на скрытом canvas. Каждый пиксель рассчитывается фрагментным шейдером на основе входных данных с использованием математики с плавающей точкой GPU. Различия в стандарте IEEE 754 FP между производителями и поколениями GPU вызывают незначительные, но стабильные вариации значений пикселей.

Шаг 3 — Считывание пикселей

Скрипт вызывает gl.readPixels() для копирования буфера пикселей RGBA из контекста WebGL в JavaScript-массив.

Шаг 4 — Хеширование

Буфер пикселей хешируется (обычно MurmurHash3 или аналогичный) для создания компактного строкового идентификатора. Этот хеш стабилен при всех перезагрузках браузера, при смене сетей и в режиме инкогнито.

// WebGL pixel hash fingerprinting — минимальный пример
function getWebGLPixelHash() {
  const canvas = document.createElement('canvas');
  canvas.width = 256;
  canvas.height = 1;
  const gl = canvas.getContext('webgl');
  if (!gl) return null;

  const vertShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertShader, `
    attribute vec2 pos;
    void main() { gl_Position = vec4(pos, 0.0, 1.0); }
  `);
  gl.compileShader(vertShader);

  // Фрагментный шейдер выполняет математику с плавающей точкой,
  // специфичную для аппаратного обеспечения GPU
  const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragShader, `
    precision highp float;
    void main() {
      float x = gl_FragCoord.x / 256.0;
      // Эти вычисления дают разные результаты на разных GPU
      gl_FragColor = vec4(
        sin(x * 3.14159),
        cos(x * 2.71828),
        tan(x * 1.41421),
        1.0
      );
    }
  `);
  gl.compileShader(fragShader);

  // ... (настройка программы, буферов и вызов draw)
  // Считывание пикселей обратно
  const pixels = new Uint8Array(256 * 4);
  gl.readPixels(0, 0, 256, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

  // Хеш буфера пикселей → стабильный идентификатор GPU
  return murmurHash(pixels);
}

Насколько уникален WebGL Pixel Hash?

НаходкаЗначениеИсточник
Энтропия от вывода рендеринга WebGL~5,7 битИсследование Fingerprint.com
Точность идентификации пользователей ПК (комбинированные сигналы)99,24%Исследование Fingerprint.com
Стабильность хеша пикселей между перезагрузкамиПостоянна до обновления драйвераNDSS 2017 / полевые измерения

Кто использует это в реальной жизни?

Коммерческие платформы идентификации устройств

Fingerprint.com, ThreatMetrix и аналогичные платформы используют WebGL pixel hash как компонент высокой энтропии в составных отпечатках устройств. Он особенно ценен для различения устройств в пределах одной модели GPU.

Защита от кросс-браузерного отслеживания

В отличие от cookie-идентификаторов, WebGL pixel hash идентичен в Chrome, Firefox, Edge и Яндекс Браузере на одной машине — если все они используют одни и те же GPU и драйвер. Это делает его ценным для «связывания» пользователей, чередующих браузеры.

Как защититься?

  • Tor Browser (наиболее сильная защита): Полностью отключает gl.readPixels(), делая pixel hash fingerprinting невозможным.
  • Brave Browser (рекомендуется для ежедневного использования): Вводит шум Farbling в вывод пикселей WebGL на уровне сессии и сайта — хеш становится ненадёжным как стабильный идентификатор.
  • Firefox с privacy.resistFingerprinting: Нормализует вывод рендеринга WebGL, возвращая общие значения вместо специфических для GPU.
  • VPN ограничения: VPN не влияет на вычисления GPU. Строка рендерера и хеш пикселей одинаковы независимо от того, через какой сервер проходит трафик. Проверьте работу VPN на whatsmy.fyi.

Часто задаваемые вопросы

Чем WebGL pixel hash отличается от строки рендерера WebGL?

Строка рендерера (считываемая через WEBGL_debug_renderer_info) — текстовый идентификатор, сообщающий модель GPU. WebGL pixel hash — числовой идентификатор, получаемый из фактического вычислительного вывода GPU. Строка рендерера идентифицирует модель; хеш пикселей различает экземпляры одной и той же модели с разными версиями драйверов.

Как часто меняется хеш пикселей?

Он меняется при обновлении драйвера GPU, смене GPU или (в некоторых браузерах) при отключении аппаратного ускорения. Сам по себе браузер не влияет на него — Chrome, Firefox и Edge на одном оборудовании возвращают одинаковый хеш.

Работает ли защита в инкогнито?

Нет защиты в стандартном режиме инкогнито. Вычисление GPU одинаково в любом режиме окна. Только браузеры с активным шумом рендеринга (Brave, Tor) производят разные хеши.

Связанные статьи

Проверьте свой IP-адрес, местоположение и оценку конфиденциальности — мгновенно.

Без логов. Без слежки. Без внешних API.

Запустить проверку →

Похожие статьи

WebGL Pixel Hash: хеш пикселей GPU как идентификатор | whatsmy.fyi