Volver al Centro de conocimiento
Huella digital

Observabilidad de aleatoriedad criptográfica y huellas del navegador

Compara Web Crypto getRandomValues con la generación aleatoria de crypto-js mediante un fixture reproducible y observaciones acotadas de privacidad.

BotBrowser Team

Documentación

Quieres la documentación estructurada de Huella digital?

Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.

BotBrowser puede repetir un fixture autorizado del mismo origen que registra disponibilidad de API y metadatos acotados de salida, pero no puede certificar la calidad de la entropía, identificar a una persona ni convertir un valor aleatorio en una huella estable. La comparación útil enfrenta el contrato de crypto.getRandomValues() controlado por el navegador con la ruta pública de crypto-js que entrega bytes aleatorios a un generador de nivel de biblioteca.

TL;DR

  • crypto.getRandomValues() es una API del navegador para llenar un array tipado; no expone una identidad reutilizable del navegador.
  • crypto-js es código de aplicación. Su ruta de números aleatorios depende de la versión, el build, los globales del runtime y la rama de fuente cargada.
  • Compara capacidad, versión de fuente, forma del array y metadatos gruesos. Nunca publiques valores aleatorios, semillas, datos de cuenta ni muestras de entropía sin ocultar.
  • Un fixture repetido puede revelar una implementación cambiada o una ruta alternativa rota, pero una salida no prueba calidad de entropía ni unicidad de huella.

Contents

Flujo que separa WEB_CRYPTO y CRYPTO_JS de un registro acotado y una frontera de privacidad.

Separar las dos fuentes aleatorias

La especificación Web Cryptography define Crypto.getRandomValues() como una operación mediada por el navegador sobre un array entero tipado. La referencia de MDN documenta los tipos admitidos, el retorno síncrono y el límite de cuota. El navegador posee la fuente subyacente y puede rechazar una vista inválida; el código de página no elige una semilla.

crypto-js tiene otro modelo de propiedad. Su árbol de fuentes público contiene un helper de palabras aleatorias usado por algoritmos de la biblioteca, con comprobaciones de capacidades y un respaldo que han cambiado entre versiones. Lee la fuente etiquetada exacta que contiene tu bundle y registra si eligió un objeto crypto del navegador, otro proveedor del runtime o un respaldo. El nombre del paquete por sí solo no prueba la rama.

La comparación trata contratos observables, no la reproducción de entropía interna. Un fixture puede indicar que existe crypto.getRandomValues, que se llenó un array tipado y que un build cargado de crypto-js produjo la forma esperada. No puede convertir ninguno de los dos resultados en un identificador estable de dispositivo. Para ampliar la revisión, consulta verificación de huella del navegador e integridad de API entre realms.

Mantén los enlaces de fuente junto al fixture: fuente aleatoria de crypto-js, versiones de crypto-js y consistencia de automatización de BotBrowser. La página de docs correspondiente cubre comprobaciones de consistencia, pero no esta comparación a nivel de fuente ni sus reglas de redacción.

Usar un fixture reproducible

Ejecuta la misma página HTTPS en un perfil nuevo declarado. El fixture siguiente registra solo nombres de rama, longitudes y un digest corto de los bytes generados; nunca guarda el valor aleatorio.

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

El fixture es reproducible porque sus entradas son fijas: fixtureId, un array del navegador de 32 bytes, una petición de 16 bytes de la biblioteca y la misma versión del paquete cargado. La salida no es determinista intencionalmente. Un traspaso JSON útil es:

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

Repite el fixture tras cambiar una sola variable: build del navegador, perfil, versión del paquete, bundler o runtime. Conserva browserVersion, os, profile, cryptoJsVersion y testedOn en el registro privado. No compares los bytes aleatorios; compara la primera capacidad o forma que cambie.

FilaCambio únicoCampos principalesResponsable
Abaselinetodos los campos del fixtureresponsable de pruebas
Bbuild del navegadorbrowserCrypto, browserLength, outcomenavegador/contexto
Cciclo de vida del perfilcapacidad y resultadoperfil
Dversión de crypto-jscryptoJsLoaded, libraryLength, outcomedependencia
Esalida del bundlercarga y ruta del métodobuild

Diagnóstico y límites

Mantener cada solicitud de Web Crypto dentro del límite en bytes

La especificación de Web Crypto exige que getRandomValues() lance QuotaExceededError cuando el byteLength del array tipado supera 65,536. Comprueba los bytes, no el número de elementos: Uint32Array(16_384) ocupa exactamente 65,536 bytes, mientras que un elemento más supera el límite. La función siguiente acepta solo Uint8Array, donde el número de elementos también equivale a los bytes; convierte las vistas de elementos más anchos a su buffer de bytes antes de usarla:

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

Esto resuelve el límite de tamaño por llamada de la API; no hace determinista un búfer mayor, no valida la calidad de la entropía ni vuelve publicables los bytes aleatorios. Conserva la clasificación de errores del fixture: una solicitud demasiado grande es un error de forma de la petición, no evidencia de una fuente débil ni de una identidad del navegador.

Si browserCrypto es falso, revisa origen, realm y contexto antes de cambiar el perfil. Si solo cambia la biblioteca, revisa el paquete resuelto y el orden de carga. Un quota-error describe un tamaño rechazado, no entropía débil. No uses un prefijo digest como huella; conserva solo campos acotados. BotBrowser puede repetir el fixture autorizado y comparar el primer campo cambiado, pero no puede certificar calidad de entropía ni una identidad.

Leer observaciones sin exagerar

ObservaciónQué respaldaQué no demuestra
browserCrypto: truela página puede llamar a la API del navegadorcalidad de entropía, fuente física o identidad
libraryLength: 16la biblioteca cargada devolvió la forma solicitadaqué proveedor entregó los bytes
quota-errorel navegador rechazó el tamaño de array solicitadoperfil roto o aleatoriedad débil
rama de cryptoJsVersion cambiadacambio de fuente o dependencia que revisarhuella del navegador o veredicto de seguridad

Si el campo del navegador cambia de true a false, revisa el contexto y el aislamiento de página antes de culpar al perfil. Si solo cambia el campo de la biblioteca, inspecciona el paquete resuelto y la fuente empaquetada. Si se repite un prefijo de digest, trátalo como un artefacto redactado que requiere repetir la prueba, no como una identidad estable. La recomendación Web Crypto y la fuente de crypto-js responden preguntas distintas y deben conservar citas separadas.

Mantener separadas huellas y aleatoriedad

Una huella reúne observaciones relativamente estables o controladas por política, como datos de user-agent, métricas de pantalla o disponibilidad de funciones. La salida aleatoria varía deliberadamente. Unir muestras aleatorias a un perfil puede crear un identificador de aplicación, pero ese identificador nace del modelo de datos de la aplicación, no de getRandomValues().

Para telemetría minimizada conserva id del fixture, rama de API, longitudes solicitadas, versión del paquete, resultado grueso y marca temporal. Descarta valores aleatorios, semillas, digests completos, identificadores de cuenta y uniones entre sitios. BotBrowser puede repetir el fixture autorizado y comparar esos campos acotados; no puede certificar una prueba de entropía de terceros, inferir a una persona desde una muestra ni garantizar que un respaldo de biblioteca sea adecuado para uso criptográfico.

Lectura siguiente

Consulta comportamiento determinista y validación con privacidad para separar repetición y minimización.

ObservaciónNecesario paraConservarDescartar
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
rama de respaldodecisión de productonombre de rama y revisión de appdatos de usuario usados por la página

Conclusión práctica

Compara getRandomValues() del navegador con la fuente pública exacta de crypto-js que carga tu bundle. Usa un fixture fijo, conserva solo metadatos de capacidad y forma, y cambia una variable por repetición. El resultado puede explicar un cambio de fuente o runtime; no puede convertir aleatoriedad en huella ni probar calidad de entropía.

Public sources

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

Este artículo forma parte de la guía: ¿Qué es la huella digital del navegador?

Lleva BotBrowser de la investigación a producción

Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.