Graine de bruit : RNG deterministe pour empreintes
Plongée détaillée dans la façon dont les graines de bruit déterministes produisent des empreintes Canvas, WebGL et Audio cohérentes entre les sessions et les pipelines CI/CD.
Vous préférez la doc produit maintenue ?
Cet article a une page équivalente dans le centre de documentation. Utilisez les docs pour le flux canonique, les flags à jour et la référence durable.
Introduction
La protection des empreintes numériques du navigateur repose souvent sur l'ajout de bruit aux sorties de rendu : de légères variations dans les pixels Canvas, les résultats de traitement audio ou les données de rendu WebGL. Ce bruit empêche la capture de l'empreinte originale spécifique à l'appareil. Cependant, si ce bruit est aléatoire, l'empreinte change à chaque chargement de page, chaque session et chaque redémarrage du navigateur. Une empreinte changeante est elle-même un signal distinctif, car les vrais appareils produisent une sortie stable et cohérente.
BotBrowser résout ce problème avec le flag --bot-noise-seed. Au lieu d'appliquer un bruit aléatoire, BotBrowser utilise un générateur de nombres pseudo-aléatoires (RNG) déterministe initialisé avec une valeur fournie par l'utilisateur. La même graine produit toujours le même motif de bruit, ce qui signifie que la même empreinte est générée à chaque fois. Cela rend la sortie d'empreinte stable entre les sessions, reproductible entre les machines et prévisible pour les tests, tout en étant différente de la sortie originale de l'appareil.
Impact sur la vie privée
La distinction entre bruit aléatoire et bruit déterministe a des implications significatives pour la vie privée.
Le bruit aléatoire crée une nouvelle identité d'empreinte à chaque session. Du point de vue d'un tracker, une empreinte qui change à chaque visite est suspecte. Les vrais navigateurs produisent des empreintes stables. Un utilisateur dont le hash Canvas change à chaque chargement de page se distingue de la grande majorité des visiteurs dont le hash Canvas reste constant pendant des semaines ou des mois. Cette instabilité peut déclencher un examen plus approfondi et des techniques de pistage plus agressives.
Le bruit déterministe, en revanche, produit une empreinte stable qui se comporte exactement comme un vrai appareil. Le hash Canvas est cohérent entre les chargements de page. L'empreinte audio est la même aujourd'hui qu'hier. La sortie WebGL reste stable entre les redémarrages du navigateur. Du point de vue de n'importe quel script de fingerprinting, le navigateur semble être un appareil normal avec une empreinte normale et immuable.
Cette stabilité est essentielle pour plusieurs cas d'usage :
- Cohérence multi-sessions : revenir sur un site web avec la même empreinte semble naturel. Arriver avec une empreinte différente à chaque fois suggère l'utilisation d'outils de confidentialité.
- Gestion de comptes : lors de la gestion de plusieurs comptes, chaque compte a besoin de sa propre identité stable. Une graine de bruit par compte garantit que chaque identité a une empreinte cohérente et distincte.
- Tests et QA : les tests automatisés qui vérifient un comportement dépendant de l'empreinte ont besoin de résultats reproductibles. Le bruit aléatoire rend les tests instables ; le bruit déterministe les rend fiables.
- Recherche : les chercheurs en vie privée qui étudient le fingerprinting ont besoin de conditions contrôlées. Une graine de bruit fixe permet la reproduction exacte des conditions expérimentales.
Contexte technique
Comment fonctionne le RNG déterministe
Un générateur de nombres aléatoires déterministe (aussi appelé générateur de nombres pseudo-aléatoires, ou PRNG) produit une séquence de nombres qui semble aléatoire mais est entièrement déterminée par son état initial, la graine. Avec la même graine, le PRNG produit toujours exactement la même séquence de nombres, dans le même ordre, peu importe quand et où il s'exécute.
BotBrowser utilise un PRNG de qualité cryptographique initialisé avec la valeur fournie via --bot-noise-seed. Lorsque le rendu Canvas a besoin de perturbation de bruit, il puise dans ce PRNG. Lorsque le traitement Audio a besoin de variation, il puise dans le même PRNG (ou un dérivé). Lorsque la sortie WebGL a besoin de modification, la même source déterministe fournit les valeurs.
Les propriétés clés sont :
- Déterminisme : même graine produit même sortie, toujours
- Indépendance : des graines différentes produisent des sorties complètement non liées
- Uniformité : la distribution du bruit semble naturelle, pas structurée
- Cohérence multiplateforme : la même graine produit la même sortie sur n'importe quel système d'exploitation hôte
Ce qui est initialisé par la graine
La graine de bruit contrôle toutes les variations liées au rendu dans BotBrowser :
- Canvas 2D : perturbations au niveau des pixels dans la sortie de rendu Canvas. Lorsqu'une page appelle
canvas.toDataURL()oucanvas.getImageData(), les données retournées incluent un bruit dérivé de la graine. - WebGL : la sortie des shaders, les données de relecture et les variations spécifiques au renderer sont déterminées par la graine.
- Audio : le traitement AudioContext (sortie d'oscillateur, données d'analyseur, comportement du compresseur dynamique) inclut une variation déterminée par la graine.
- Polices : les micro-variations de mesure des glyphes sont initialisées par la graine, garantissant des résultats
measureText()cohérents.
Chacun de ces sous-systèmes utilise une portion du flux de sortie du PRNG, garantissant que le bruit appliqué à Canvas n'interfère pas avec le bruit appliqué à Audio, tandis que les deux restent déterministes pour la même valeur de graine.
Espace de graines et collisions
La graine de bruit est une valeur entière. Des valeurs entières différentes produisent des sorties d'empreinte complètement différentes. Il n'y a pas de relation prévisible entre des valeurs de graine adjacentes (la graine 42 et la graine 43 produisent des empreintes entièrement non liées). L'espace des empreintes possibles est suffisamment grand pour que les collisions accidentelles (deux utilisateurs choisissant la même graine par hasard) soient négligeables en pratique.
Interaction avec les profils
La graine de bruit fonctionne en conjonction avec, et non en remplacement du profil d'empreinte. Le profil définit les caractéristiques de l'appareil : résolution d'écran, modèle de GPU, plateforme, version du navigateur, polices et tous les autres signaux matériels/logiciels. La graine de bruit contrôle la variation de rendu au sein de l'identité d'appareil de ce profil.
Pensez-y ainsi : le profil définit quel type d'appareil est présenté, et la graine de bruit détermine les caractéristiques de rendu spécifiques de cette "instance" particulière de l'appareil. Deux instances avec le même profil mais des graines différentes ressemblent à deux appareils physiques différents du même modèle. Deux instances avec le même profil et la même graine ressemblent au même appareil.
Approches de protection courantes et leurs limites
Bruit aléatoire (sans graine)
Les outils qui ajoutent du bruit aléatoire aux sorties Canvas, WebGL et Audio créent une empreinte différente à chaque démarrage du navigateur. Les problèmes :
- L'instabilité de l'empreinte déclenche la suspicion des trackers
- Les tests automatisés ne peuvent pas compter sur une sortie cohérente
- La continuité de session est impossible (chaque visite ressemble à un nouvel appareil)
- L'analyse statistique du motif de bruit peut révéler son origine artificielle
Sortie synthétique fixe
Certains outils remplacent la sortie Canvas ou Audio par une valeur codée en dur unique. Cela produit de la stabilité mais a ses propres problèmes :
- Tous les utilisateurs de l'outil produisent la même empreinte, créant un cluster détectable
- La sortie fixe peut ne pas correspondre aux autres signaux de l'appareil (GPU, polices, système d'exploitation)
- Si les données codées en dur sont découvertes, tous les utilisateurs sont immédiatement identifiables
Bruit basé sur les extensions
Les extensions de navigateur qui injectent du bruit font face aux limites discutées dans d'autres articles : elles opèrent au niveau de l'API JavaScript, peuvent être détectées par des vérifications de descripteurs de propriétés, et ne peuvent pas contrôler tous les chemins de rendu de manière cohérente.
Pas de bruit (profil uniquement)
Utiliser un profil sans aucun bruit produit une sortie déterminée par le pipeline de rendu du matériel hôte. Bien que le profil contrôle les valeurs rapportées, le rendu réel reflète toujours les caractéristiques du GPU et des polices de l'hôte. L'ajout de bruit initialisé par graine garantit que la sortie de rendu est contrôlée plutôt que divulguée depuis l'hôte.
L'approche de BotBrowser au niveau du moteur
Le flag --bot-noise-seed
Le flag --bot-noise-seed de BotBrowser accepte une valeur entière qui initialise tout le bruit lié au rendu :
chrome --bot-profile="/path/to/profile.enc" \
--bot-noise-seed=42 \
--user-data-dir="$(mktemp -d)"
Avec cette configuration :
- Canvas
toDataURL()etgetImageData()retournent les mêmes données à chaque fois - Les opérations de relecture WebGL produisent des résultats identiques entre les sessions
- Le traitement audio (via AudioContext) génère les mêmes données de forme d'onde
- Les métriques de polices sont cohérentes entre les redémarrages du navigateur
- Le hash d'empreinte (hash Canvas, hash Audio, hash WebGL) est stable
Contrôle du bruit Canvas
BotBrowser fournit un contrôle fin du bruit Canvas via --bot-config-noise-canvas :
# Activer le bruit Canvas avec une graine déterministe
chrome --bot-profile="/path/to/profile.enc" \
--bot-noise-seed=42 \
--bot-config-noise-canvas=true
# Désactiver le bruit Canvas spécifiquement
chrome --bot-profile="/path/to/profile.enc" \
--bot-noise-seed=42 \
--bot-config-noise-canvas=false
Lorsque le bruit Canvas est activé, la graine contrôle la perturbation exacte. Lorsqu'il est désactivé, la sortie Canvas est déterminée entièrement par le profil et le moteur de rendu sans bruit supplémentaire.
Gestion multi-identités
Pour gérer plusieurs identités distinctes, assignez une graine de bruit unique à chacune :
# Identité A : empreinte cohérente pour le Compte A
chrome --bot-profile="/profiles/profile-a.enc" \
--bot-noise-seed=1001 \
--user-data-dir="/data/account-a"
# Identité B : empreinte différente mais tout aussi cohérente
chrome --bot-profile="/profiles/profile-b.enc" \
--bot-noise-seed=2002 \
--user-data-dir="/data/account-b"
# Identité C : troisième identité distincte
chrome --bot-profile="/profiles/profile-c.enc" \
--bot-noise-seed=3003 \
--user-data-dir="/data/account-c"
Chaque identité a son propre profil (définissant les caractéristiques de l'appareil) et sa propre graine de bruit (définissant les variations de rendu). Les empreintes sont distinctes les unes des autres et stables entre les sessions.
Reproductibilité inter-machines
L'une des propriétés les plus puissantes du bruit déterministe est la reproductibilité inter-machines. Le même profil et la même graine produisent la même empreinte sur n'importe quelle machine hôte, indépendamment de :
- Le système d'exploitation hôte (Windows, macOS, Linux)
- Le modèle de GPU hôte
- Le jeu de polices hôte
- La résolution d'écran hôte
- Conteneur Docker vs. machine physique vs. machine virtuelle
Cela rend --bot-noise-seed essentiel pour les déploiements distribués où plusieurs machines doivent présenter la même identité, ou lorsqu'un pipeline CI/CD doit reproduire les conditions exactes d'empreinte d'un environnement de production.
Configuration et utilisation
Utilisation CLI de base
# Empreinte déterministe avec graine
chrome --bot-profile="/path/to/profile.enc" \
--bot-noise-seed=42 \
--user-data-dir="$(mktemp -d)"
Exemple de pipeline CI/CD
# Même profil et graine en CI produit la même empreinte qu'en production
chrome --bot-profile="/profiles/production-identity.enc" \
--bot-noise-seed=98765 \
--bot-time-scale=1.0 \
--bot-fps=60 \
--headless \
--user-data-dir="$(mktemp -d)"
Intégration Playwright
const { chromium } = require('playwright-core');
(async () => {
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-noise-seed=42',
],
headless: true,
});
const context = await browser.newContext({ viewport: null });
const page = await context.newPage();
// Le hash Canvas sera le même à chaque exécution
const canvasHash = await page.evaluate(() => {
const c = document.createElement('canvas');
c.width = 200;
c.height = 50;
const ctx = c.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillStyle = '#333';
ctx.fillText('Deterministic test', 2, 2);
ctx.fillStyle = 'rgba(0, 50, 255, 0.5)';
ctx.fillRect(50, 10, 100, 30);
return c.toDataURL();
});
console.log('Canvas hash:', canvasHash.substring(0, 80) + '...');
await browser.close();
})();
Intégration Puppeteer
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-noise-seed=42',
'--bot-config-noise-canvas=true',
],
headless: true,
defaultViewport: null,
});
const page = await browser.newPage();
await page.goto('about:blank');
// L'empreinte audio sera aussi déterministe
const audioHash = await page.evaluate(() => {
return new Promise(resolve => {
const ctx = new OfflineAudioContext(1, 44100, 44100);
const osc = ctx.createOscillator();
osc.type = 'triangle';
osc.frequency.value = 10000;
osc.connect(ctx.destination);
osc.start(0);
ctx.startRendering().then(buffer => {
const data = buffer.getChannelData(0).slice(4500, 5000);
const sum = data.reduce((a, b) => a + Math.abs(b), 0);
resolve(sum.toFixed(10));
});
});
});
console.log('Audio hash:', audioHash);
await browser.close();
})();
Configuration déterministe complète
Pour une reproductibilité maximale, combinez la graine de bruit avec le contrôle du timing et du framerate :
chrome --bot-profile="/path/to/profile.enc" \
--bot-noise-seed=42 \
--bot-time-scale=1.0 \
--bot-fps=60 \
--bot-config-noise-canvas=true \
--user-data-dir="$(mktemp -d)"
Vérification
Pour vérifier le comportement déterministe, exécutez la même configuration deux fois et comparez :
// Exécution 1 : capturer les hash d'empreinte
const run1Canvas = await page.evaluate(() => {
const c = document.createElement('canvas');
c.width = 200; c.height = 50;
const ctx = c.getContext('2d');
ctx.font = '14px Arial';
ctx.fillText('Test string', 10, 25);
return c.toDataURL();
});
// Exécution 2 : même profil, même graine, devrait produire un hash identique
// (redémarrer le navigateur entre les exécutions)
const run2Canvas = await page.evaluate(() => {
const c = document.createElement('canvas');
c.width = 200; c.height = 50;
const ctx = c.getContext('2d');
ctx.font = '14px Arial';
ctx.fillText('Test string', 10, 25);
return c.toDataURL();
});
console.log('Canvas match:', run1Canvas === run2Canvas);
// Devrait afficher : Canvas match: true
Points de vérification :
- La sortie Canvas est identique entre les redémarrages du navigateur avec la même graine
- Le traitement audio produit les mêmes valeurs de hash entre les sessions
- Les données de relecture WebGL correspondent entre les exécutions
- Des graines différentes produisent des sorties différentes (mais individuellement stables)
- La même graine sur des machines hôtes différentes produit la même empreinte
- Les outils de test d'empreinte (CreepJS, BrowserLeaks) montrent des hash stables
Bonnes pratiques
-
Choisissez des graines uniques par identité. Chaque identité de navigateur devrait avoir sa propre graine de bruit. Utiliser la même graine pour plusieurs identités les fait produire la même sortie de rendu, ce qui peut les lier.
-
Stockez les graines de manière sécurisée. La graine de bruit fait partie de la configuration d'identité. Traitez-la comme une donnée sensible aux côtés du chemin de profil et du répertoire de données utilisateur.
-
Utilisez des graines en CI/CD. Pour les tests automatisés, spécifiez toujours une graine de bruit pour garantir des résultats déterministes. Sans graine, la sortie de rendu peut varier entre les exécutions de test.
-
Combinez avec
--bot-time-scale. Pour un déterminisme complet, contrôlez à la fois le bruit de rendu et les signaux de timing. La graine de bruit gère Canvas/Audio/WebGL, tandis que--bot-time-scalegère le timing de performance. -
Documentez les attributions de graines. Dans les déploiements multi-identités, maintenez un mapping de quelle graine est attribuée à quelle identité. Cela garantit que vous pouvez reproduire l'empreinte exacte de n'importe quelle identité.
-
Évitez les graines séquentielles pour les identités liées. Bien que les graines séquentielles (1, 2, 3) produisent des sorties non liées, utiliser un mapping délibéré (comme le hachage des identifiants de compte) offre une meilleure clarté organisationnelle.
Questions fréquentes
La graine de bruit affecte-t-elle le contenu de la page ou la qualité du rendu ?
Non. Le bruit est appliqué au niveau sous-pixel pour Canvas et à une précision similaire pour Audio et WebGL. Les variations sont invisibles à l'œil nu et inaudibles. Les pages ont la même apparence et fonctionnent de manière identique quelle que soit la valeur de la graine.
Deux utilisateurs avec la même graine peuvent-ils être liés ?
Si deux utilisateurs utilisent le même profil ET la même graine de bruit, leur sortie de rendu sera identique, ce qui pourrait théoriquement les lier. C'est pourquoi chaque identité devrait utiliser une graine unique. Des profils différents avec la même graine produisent des sorties différentes car le profil influence aussi le rendu.
Que se passe-t-il sans --bot-noise-seed ?
Sans graine de bruit, BotBrowser applique toujours les caractéristiques d'appareil du profil, mais le bruit de rendu (s'il est activé) peut utiliser une graine aléatoire de session. Cela fournit une sortie différente de celle de l'hôte mais ne garantit pas la cohérence entre les sessions. Pour des empreintes stables, spécifiez toujours une graine de bruit.
La graine doit-elle être un type spécifique de nombre ?
La graine est un entier. N'importe quelle valeur entière fonctionne. Il n'y a aucun avantage à choisir de grands nombres, des nombres premiers ou tout autre motif spécifique. Utilisez simplement une valeur unique par identité.
Puis-je changer la graine pour obtenir une nouvelle empreinte ?
Oui. Changer la graine de bruit tout en gardant le même profil produit une nouvelle empreinte distincte. C'est utile lorsque vous devez alterner les identités tout en maintenant la même classe d'appareil (même profil, caractéristiques de rendu différentes).
Comment --bot-noise-seed interagit-il avec --bot-config-noise-canvas ?
--bot-config-noise-canvas active ou désactive l'application du bruit Canvas. --bot-noise-seed contrôle le motif de bruit lorsqu'il est appliqué. Si le bruit Canvas est désactivé, la graine affecte toujours le bruit Audio et WebGL. Si le bruit Canvas est activé, la graine le rend déterministe.
La graine de bruit est-elle compatible avec tous les profils ?
Oui. La graine de bruit est indépendante de la configuration d'appareil du profil. N'importe quelle graine fonctionne avec n'importe quel profil. La graine contrôle la variation de rendu, tandis que le profil contrôle l'identité de l'appareil.
Les services de fingerprinting peuvent-ils détecter que le bruit est déterministe ?
Non. Le motif de bruit produit par une graine déterministe est statistiquement indiscernable de la variation naturelle du matériel. Le déterminisme n'est observable que si la même graine est testée plusieurs fois et que la même sortie exacte est confirmée, ce qui est le comportement prévu (stabilité, pas aléatoire).
Résumé
Le flag --bot-noise-seed est le fondement de la protection reproductible des empreintes dans BotBrowser. En initialisant un RNG déterministe qui contrôle les variations de rendu Canvas, WebGL, Audio et polices, il produit des empreintes stables entre les sessions, reproductibles entre les machines et indiscernables de la sortie naturelle d'un appareil. Combiné avec la gestion des profils, la protection Canvas, le contrôle des empreintes audio et le timing de performance, la reproductibilité des graines de bruit permet des identités d'empreinte cohérentes et prévisibles pour la protection de la vie privée, la gestion multi-comptes, les tests et la recherche.
Articles Connexes
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.