Números aleatorios seguros en Python con secrets

Publicado el: 11/07/2026
Tempo de leitura: 5 minutos
Geração de números aleatórios seguros usando secrets em Python

El módulo secrets de Python genera valores aleatorios adecuados para contraseñas, tokens de recuperación, identificadores temporales y otros datos relacionados con seguridad. Aunque el módulo random es excelente para juegos y simulaciones, sus resultados son predecibles si un atacante conoce suficiente información sobre el estado interno del generador.

Cuando la imprevisibilidad forma parte de la seguridad, debes utilizar una fuente criptográficamente segura. En esta guía aprenderás a crear enteros, elegir elementos, generar tokens, construir contraseñas, comparar secretos y evitar errores frecuentes.

Random y secrets no resuelven el mismo problema

El módulo random utiliza un generador pseudoaleatorio diseñado para velocidad y reproducibilidad. Esto resulta útil cuando necesitas repetir una simulación con la misma semilla. No resulta apropiado para claves, enlaces privados o códigos de autenticación.

El módulo secrets utiliza la fuente de aleatoriedad proporcionada por el sistema operativo. La documentación oficial de secrets recomienda este módulo para contraseñas, autenticación y tokens de seguridad.

Para comprender el uso no criptográfico, consulta la guía del módulo random en Python.

Generar un entero seguro con randbelow()

import secrets

number = secrets.randbelow(100)
print(number)

randbelow(100) devuelve un entero desde 0 hasta 99. El límite superior queda excluido. Para simular un dado del 1 al 6:

dice = secrets.randbelow(6) + 1
print(dice)

Aunque este ejemplo funciona, un juego normal no necesita el coste adicional de una fuente criptográfica. Reserva secrets para escenarios donde la predicción tenga consecuencias.

Crear bits aleatorios con randbits()

import secrets

value = secrets.randbits(128)
print(value)
print(value.bit_length())

randbits(k) genera un entero con hasta k bits aleatorios. Puede servir como base para identificadores internos, pero las funciones token_hex() y token_urlsafe() suelen ser más cómodas para transmitir valores.

Elegir un elemento de forma segura

import secrets

alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
character = secrets.choice(alphabet)
print(character)

choice() selecciona un elemento de una secuencia no vacía. Puedes repetir la operación para construir un código:

code = "".join(
    secrets.choice(alphabet)
    for _ in range(8)
)
print(code)

La guía de strings en Python explica join(), validación y manipulación de texto.

Generar tokens binarios, hexadecimales y seguros para URL

import secrets

raw_token = secrets.token_bytes(32)
hex_token = secrets.token_hex(32)
url_token = secrets.token_urlsafe(32)

print(raw_token)
print(hex_token)
print(url_token)
  • token_bytes() devuelve bytes sin codificar.
  • token_hex() devuelve texto hexadecimal.
  • token_urlsafe() devuelve texto compatible con URLs y formularios.

El argumento representa la cantidad de bytes de entropía, no la longitud final exacta del texto. Un token hexadecimal utiliza dos caracteres por byte; uno codificado para URL suele ser aproximadamente un tercio más largo.

Crear un enlace de recuperación

import secrets
from urllib.parse import urlencode


def create_reset_url(base_url):
    token = secrets.token_urlsafe(32)
    query = urlencode({"token": token})
    return token, f"{base_url}?{query}"


token, url = create_reset_url(
    "https://example.com/reset-password"
)
print(url)

La aplicación debe guardar una representación protegida del token, asociarla a un usuario y definir una expiración. No basta con generar un valor aleatorio; también debes controlar almacenamiento, uso único, revocación y tiempo de vida.

Generar una contraseña segura

import secrets
import string


def generate_password(length=20):
    if length < 12:
        raise ValueError(
            "La longitud mínima es 12"
        )

    alphabet = (
        string.ascii_letters
        + string.digits
        + "!@#$%&*+-_"
    )

    return "".join(
        secrets.choice(alphabet)
        for _ in range(length)
    )


print(generate_password())

Una contraseña aleatoria larga suele ser más resistente que una corta con reglas complicadas. La guía del generador seguro de contraseñas en Python desarrolla un proyecto completo con validación y personalización.

Garantizar requisitos en la contraseña

Cuando una plataforma exige tipos específicos de caracteres, genera hasta cumplir todas las condiciones:

import secrets
import string


def generate_compliant_password(length=20):
    alphabet = (
        string.ascii_letters
        + string.digits
        + "!@#$%&*+-_"
    )

    while True:
        password = "".join(
            secrets.choice(alphabet)
            for _ in range(length)
        )

        if not any(c.islower() for c in password):
            continue
        if not any(c.isupper() for c in password):
            continue
        if not any(c.isdigit() for c in password):
            continue
        if not any(c in "!@#$%&*+-_" for c in password):
            continue

        return password

No registres la contraseña generada. La guía de logging en Python explica cómo evitar información sensible en archivos de registro.

Comparar tokens con compare_digest()

import secrets

stored = "a4c8f2d1"
provided = "a4c8f2d1"

if secrets.compare_digest(stored, provided):
    print("Token válido")
else:
    print("Token inválido")

compare_digest() reduce la exposición a ataques basados en diferencias de tiempo durante la comparación. Ambos valores deben ser del mismo tipo: bytes con bytes o strings ASCII con strings compatibles.

No confundas tokens con cifrado

Un token aleatorio no cifra información. secrets puede generar material aleatorio para bibliotecas criptográficas, pero no implementa por sí mismo cifrado, hashing de contraseñas o firmas digitales.

La guía de seguridad de OWASP sobre almacenamiento de contraseñas recomienda algoritmos especializados y configuraciones resistentes. Nunca guardes contraseñas en texto plano ni intentes inventar un sistema criptográfico propio.

Validar longitud y configuración

def validate_token_size(size):
    if not isinstance(size, int):
        raise TypeError("El tamaño debe ser entero")
    if size < 16:
        raise ValueError(
            "Utiliza al menos 16 bytes"
        )
    return size

La cantidad adecuada depende del riesgo y del tiempo de vida del token. Para tokens sensibles y duraderos, 32 bytes es una elección común. Evita tamaños pequeños solamente para obtener URLs más cortas.

Ejemplo: códigos de invitación únicos

import secrets


def create_invitation_code(existing_codes):
    while True:
        code = secrets.token_urlsafe(12)

        if code not in existing_codes:
            existing_codes.add(code)
            return code


used = set()

for _ in range(5):
    print(create_invitation_code(used))

La comprobación evita una colisión dentro del conjunto actual. La guía de sets en Python explica por qué la pertenencia es eficiente en esta estructura.

Manejo de errores

Las funciones de secrets suelen ser sencillas, pero el código que almacena o entrega tokens puede fallar. Captura excepciones específicas en la capa correspondiente:

try:
    token = secrets.token_urlsafe(32)
    save_token(token)
except DatabaseError as error:
    logger.exception(
        "No fue posible guardar el token"
    )
    raise

La guía de try y except en Python explica cómo conservar el traceback y evitar bloques demasiado amplios.

Errores frecuentes

  • Usar random para contraseñas o recuperación de cuentas.
  • Crear tokens demasiado cortos.
  • Registrar tokens, claves o contraseñas.
  • Reutilizar un token después de su primer uso.
  • No establecer una expiración.
  • Guardar contraseñas en lugar de hashes seguros.
  • Confundir aleatoriedad con cifrado.
  • Comparar secretos sensibles con lógica casera.

Conclusión

Utiliza secrets cuando un valor impredecible proteja una cuenta, sesión o recurso. Domina randbelow(), choice(), token_hex(), token_urlsafe() y compare_digest(). Después completa la solución con expiración, almacenamiento seguro, uso único y registros que nunca expongan información confidencial.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Como converter código Python para C usando Cython
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Cython: cómo acelerar Python compilando a C

    Aprende Cython para acelerar Python: archivos .pyx, cdef, cpdef, tipos C, memoryviews, GIL, NumPy, compilación y benchmarks.

    Ler mais

    Tempo de leitura: 6 minutos
    11/07/2026
    Uso do operador ternário em Python para condições rápidas
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Operador ternario en Python: guía clara y práctica

    Aprende el operador ternario en Python: sintaxis, asignaciones, listas, return, anidación, errores frecuentes y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Logo lambda usado no Half-Life
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Funciones lambda en Python: guía con ejemplos

    Aprende funciones lambda en Python con sorted, map, filter, closures, callbacks, type hints, errores comunes y criterios de legibilidad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Como usar o comando return em funções Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Return en Python: cómo devolver valores correctamente

    Aprende cómo funciona return en Python, su diferencia con print, múltiples valores, None, type hints, excepciones y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Explicação prática de args e kwargs em funções Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Args y kwargs en Python: guía completa

    Aprende *args y **kwargs en Python, desempaquetado, parámetros flexibles, errores comunes, type hints y diseño de funciones claras.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Uso do with para abrir arquivos com segurança em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Sentencia with en Python: archivos seguros y contextos

    Aprende la sentencia with en Python para abrir archivos con seguridad, manejar errores, usar context managers, contextlib y varios recursos.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026