Cómo se crean las cadenas aleatorias
Cada carácter se elige por separado entre los caracteres que has marcado, con crypto.getRandomValues, el generador de números aleatorios criptográficamente seguro del navegador, la misma fuente que se usa para las claves de cifrado. Un simple número aleatorio módulo el número de caracteres haría algo más probables algunos caracteres; esta página vuelve a sortear siempre que un valor aleatorio cae en el resto desigual, así que todos los caracteres tienen exactamente la misma probabilidad. La fortaleza de una cadena se mide en bits de entropía:
bits = length × log2(characters to choose from) 32 × log2(62) = 32 × 5.954 ≈ 190.5 bits
Cada bit duplica el número de intentos que necesita un atacante. Un prefijo como sk_ no añade nada, porque es igual en todas las cadenas; omitir los caracteres que se parecen resta un poco, porque hay menos caracteres entre los que elegir. Math.random(), que usan muchos generadores rápidos, no es seguro: su salida se puede predecir a partir de valores anteriores.
Ejemplo
Una cadena de 32 caracteres con letras y dígitos tiene 62 opciones por carácter, así que 32 × log2(62) ≈ 190,5 bits: mucho más de lo que se puede adivinar. 32 caracteres hex llevan 32 × 4 = 128 bits, lo mismo que 16 bytes aleatorios. Base64url usa 64 caracteres, de 6 bits cada uno, así que 43 de ellos contienen 258 bits, lo que codifican 32 bytes aleatorios. Un código de 6 dígitos tiene solo un millón de posibilidades (19,9 bits): en una lista de 500 códigos así, la probabilidad de que dos sean iguales ya es de aproximadamente un 11,7 %.
En el servidor
Para crear cadenas aleatorias en un servidor Linux o en un script de despliegue, usa la fuente aleatoria segura del sistema, /dev/urandom, mediante openssl o tr:
openssl rand -hex 16 # 32 hex characters
openssl rand -base64 32 | tr '+/' '-_' | tr -d '='
head -c 500 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 32Preguntas
¿Son seguras estas cadenas aleatorias?
Sí. Salen de crypto.getRandomValues, el generador de números aleatorios criptográficamente seguro de tu navegador, y cada carácter se elige sin sesgo. Se crean en tu dispositivo y nunca se envían a un servidor, así que nadie más las ve. Para claves y tokens, usa al menos 128 bits de entropía, como 22 letras y dígitos o 32 caracteres hex.
¿Cómo genero una cadena aleatoria de 32 caracteres?
Pon la longitud en 32, que es el valor predeterminado, y elige los caracteres: letras y dígitos dan unos 190 bits, hex da exactamente 128. En un servidor, openssl rand -hex 16 imprime 32 caracteres hex aleatorios. En Python: secrets.token_hex(16), o secrets.token_urlsafe(24) para 32 caracteres Base64url.
¿Qué longitud debe tener una clave de API o un token aleatorio?
Al menos 128 bits de entropía, para que no se pueda adivinar ni con miles de millones de intentos por segundo. Son 22 letras y dígitos, 32 caracteres hex o 22 caracteres Base64url. Muchos servicios usan de 32 a 40 caracteres con un prefijo como sk_ que indica para qué es la clave, lo que ayuda a los escáneres de secretos a encontrar claves filtradas.
¿Qué diferencia hay entre las cadenas hex y Base64url?
Hex usa 16 caracteres (0–9 y a–f), así que cada uno aporta 4 bits. Base64url usa 64 (letras, dígitos, - y _), así que cada uno aporta 6 bits y la cadena es un tercio más corta con la misma fortaleza. Ambos son seguros en URL, nombres de archivo y archivos de configuración. Hex es más fácil de leer; Base64url es más compacto.
¿Pueden dos cadenas generadas ser iguales?
Con longitud suficiente, prácticamente nunca: con cadenas de 128 bits harían falta unas 2^64, 18 trillones, para que una repetición fuera probable. Las cadenas cortas se repiten antes de lo que podrías pensar, por la paradoja del cumpleaños: entre 500 códigos de seis dígitos, dos son iguales cerca del 12 % de las veces. La página te avisa cuando es probable que haya una repetición en tu lista.