Retour au Centre de connaissances
Empreinte

Observabilité de l’aléa cryptographique et empreintes du navigateur

Comparez Web Crypto getRandomValues et la génération aléatoire de crypto-js avec un fixture reproductible et des observations limitées pour la confidentialité.

BotBrowser Team

Documentation

Vous voulez la documentation structurée pour Empreinte ?

Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.

BotBrowser peut rejouer un fixture autorisé de même origine qui enregistre la disponibilité de l’API et des métadonnées de sortie limitées, mais il ne peut pas certifier la qualité de l’entropie, identifier une personne ni transformer une valeur aléatoire en empreinte stable. La comparaison utile oppose le contrat de crypto.getRandomValues() géré par le navigateur au chemin public de crypto-js qui fournit des octets aléatoires à un générateur de bibliothèque.

TL;DR

  • crypto.getRandomValues() est une API du navigateur qui remplit un tableau typé ; elle n’expose pas une identité réutilisable du navigateur.
  • crypto-js est du code applicatif. Son chemin aléatoire dépend de la version, du build, des globaux du runtime et de la branche source chargée.
  • Comparez capacité, version source, forme du tableau et métadonnées grossières. Ne publiez jamais valeurs aléatoires, graines, données de compte ou échantillons d’entropie.
  • Un fixture répété peut révéler une implémentation modifiée ou un repli cassé, mais une sortie ne prouve ni qualité d’entropie ni unicité d’empreinte.

Contents

Flux séparant WEB_CRYPTO et CRYPTO_JS d’un relevé limité et d’une frontière de confidentialité.

Séparer les deux sources aléatoires

La spécification Web Cryptography définit Crypto.getRandomValues() comme une opération médiée par le navigateur sur un tableau entier typé. La référence MDN documente les types acceptés, le retour synchrone et la limite de quota. Le navigateur possède la source sous-jacente et peut refuser une vue invalide ; le code de la page ne choisit pas de graine.

crypto-js suit un autre modèle de propriété. Son arbre source public contient un helper de mots aléatoires utilisé par les algorithmes de la bibliothèque, avec des vérifications de capacités et un repli qui ont évolué entre les versions. Lisez la source taguée exacte incluse dans votre bundle, puis notez si elle a choisi un objet crypto du navigateur, un autre fournisseur du runtime ou un repli. Le nom du paquet seul ne prouve pas la branche.

La comparaison porte donc sur des contrats observables, pas sur la reproduction de l’entropie interne. Un fixture peut signaler que crypto.getRandomValues existe, qu’un tableau typé a été rempli et qu’un build crypto-js chargé a produit la forme attendue. Il ne peut transformer l’un ou l’autre résultat en identifiant stable de l’appareil. Pour une revue connexe, consultez vérification d’empreinte du navigateur et intégrité des API entre realms.

Gardez les sources près du fixture : source aléatoire crypto-js, versions crypto-js et cohérence d’automatisation BotBrowser. La page docs correspondante couvre les contrôles de cohérence, pas cette comparaison au niveau source ni ses règles de rédaction.

Utiliser un fixture reproductible

Exécutez la même page HTTPS avec un profil neuf déclaré. Le fixture ci-dessous enregistre uniquement les noms de branche, les longueurs et un court digest des octets générés ; il ne conserve jamais la valeur aléatoire.

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;
}

Le fixture est reproductible car ses entrées sont fixes : fixtureId, un tableau navigateur de 32 octets, une demande bibliothèque de 16 octets et la même version du paquet chargé. La sortie n’est volontairement pas déterministe. Un transfert JSON utile est :

{
  "fixtureId": "crypto-randomness-01",
  "browserCrypto": true,
  "cryptoJsLoaded": true,
  "browserLength": 32,
  "libraryLength": 16,
  "digestPrefix": "redacted",
  "outcome": "observed"
}

Répétez le fixture après avoir changé une seule variable : build du navigateur, profil, version du paquet, bundler ou runtime. Gardez browserVersion, os, profile, cryptoJsVersion et testedOn dans le relevé privé. Ne comparez pas les octets aléatoires ; comparez le premier champ de capacité ou de forme qui change.

LigneChangement uniqueChamps principauxResponsable
Abaselinetous les champs du fixtureresponsable des tests
Bbuild du navigateurbrowserCrypto, browserLength, outcomenavigateur/contexte
Ccycle de vie du profilcapacité et résultatprofil
Dversion de crypto-jscryptoJsLoaded, libraryLength, outcomedépendance
Esortie du bundlerchargement et chemin de méthodebuild

Diagnostic et limites

Garder chaque appel Web Crypto sous la limite en octets

La spécification Web Crypto impose à getRandomValues() de lever QuotaExceededError lorsque le byteLength du tableau typé dépasse 65,536. Vérifiez les octets, pas le nombre d'éléments : Uint32Array(16_384) occupe exactement 65,536 octets, tandis qu'un élément de plus dépasse la limite. La fonction ci-dessous accepte uniquement Uint8Array, où le nombre d'éléments correspond au nombre d'octets ; convertissez les vues à éléments plus larges en vue d'octets avant de l'utiliser :

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;
}

Cela traite la limite de taille par appel de l'API ; cela ne rend pas déterministe un tampon plus grand, ne valide pas la qualité de l'entropie et ne rend pas les octets aléatoires publiables. Conservez la classification des erreurs du fixture : une demande trop grande est une erreur de forme de requête, pas la preuve d'une source faible ni d'une identité du navigateur.

Si browserCrypto est faux, vérifiez origine, realm et contexte avant de changer le profil. Si seule la bibliothèque change, inspectez le paquet résolu et l’ordre de chargement. Un quota-error décrit une taille refusée, pas une entropie faible. N’utilisez pas un préfixe de digest comme empreinte ; gardez seulement les champs limités. BotBrowser peut rejouer le fixture autorisé et comparer le premier champ modifié, mais ne peut pas certifier l’entropie ni une identité.

Lire les observations sans extrapoler

ObservationCe qu’elle étayeCe qu’elle ne prouve pas
browserCrypto: truela page peut appeler l’API du navigateurqualité d’entropie, source matérielle ou identité
libraryLength: 16la bibliothèque chargée a rendu la forme demandéele fournisseur qui a fourni les octets
quota-errorle navigateur a refusé la taille demandéeprofil défectueux ou aléa faible
branche cryptoJsVersion modifiéechangement de source ou dépendance à examinerempreinte du navigateur ou verdict de sécurité

Si le champ navigateur passe de true à false, vérifiez le contexte et l’isolation de la page avant d’accuser le profil. Si seul le champ bibliothèque change, inspectez le paquet résolu et la source bundlée. Si un préfixe de digest se répète, traitez-le comme un artefact masqué qui exige une nouvelle exécution, pas comme une identité stable. La recommandation Web Crypto et la source crypto-js répondent à des questions différentes et doivent rester des citations séparées.

Distinguer empreintes et aléa

Une empreinte rassemble des observations relativement stables ou contrôlées par politique, comme les données user-agent, les métriques d’écran ou la disponibilité de fonctions. Une sortie aléatoire varie délibérément. Relier des échantillons aléatoires à un profil peut créer un identifiant applicatif, mais cet identifiant vient du modèle de données de l’application, pas de getRandomValues().

Pour une télémétrie minimisée, conservez l’id du fixture, la branche API, les longueurs demandées, la version du paquet, le résultat grossier et l’horodatage. Supprimez valeurs aléatoires, graines, digests complets, identifiants de compte et rapprochements intersites. BotBrowser peut rejouer le fixture autorisé et comparer ces champs limités ; il ne peut pas certifier un test d’entropie tiers, déduire une personne d’un échantillon ni garantir qu’un repli de bibliothèque convient à un usage cryptographique.

Lecture suivante

Voir le comportement déterministe et la validation respectueuse de la vie privée pour séparer répétition et minimisation.

ObservationNécessaire pourConserverSupprimer
available or errorcompatibility supportfixture id and coarse stateraw bytes and stack traces
requested array lengthregression triagelength and browser majorcomplete sample values
seeded fixture digestrepeatability testfixture revision and test-only digestproduction account linkage
token reuse countlifecycle bugcount and expiry buckettoken text and endpoint URL
branche de replidécision produitnom de branche et révision de l’applicationdonnées utilisées par la page

Conclusion pratique

Comparez getRandomValues() du navigateur avec la source publique exacte de crypto-js chargée par votre bundle. Utilisez un fixture fixe, conservez seulement les métadonnées de capacité et de forme, puis changez une variable par exécution. Le résultat peut expliquer un changement de source ou de runtime ; il ne transforme pas l’aléa en empreinte et ne prouve pas la qualité d’entropie.

Public sources

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

Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?

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.