En el post anterior vimos que la entropía solo cuenta cuando la aleatoriedad es real. El gestor de contraseñas resuelve el 99% de los casos. Pero para la clave maestra, el arranque del portátil o las pocas contraseñas que necesitas memorizar sin depender del portapapeles, la pregunta sigue en pie: ¿cómo generas entropía sin caer en el sesgo de elegir palabras que “suenan bien”?
Tales Vault System (repositorio tale) invierte el flujo habitual. Primero la contraseña (CSPRNG). Después la historia mnemotécnica, derivada con reglas fijas. Tú no eliges las letras; en el modo interactivo solo eliges entre candidatas válidas si quieres personalizar la frase.
El problema que no resuelve un gestor
Un gestor guarda cien contraseñas. Pero alguien tiene que recordar la clave que abre el gestor. Y a veces necesitas teclear una contraseña en un entorno donde pegar desde el portapapeles no es opción.
Las soluciones habituales fallan por el mismo motivo:
| Enfoque | Flujo | Problema |
|---|---|---|
| ”Mi frase favorita” | Frase → contraseña | Patrones humanos, entropía baja |
| Leetspeak | Palabra + sustituciones | Cracking moderno lo anticipa |
| xkcd sin dados | Cuatro palabras que eliges | Distribución sesgada por letra inicial |
| Diceware | Palabras aleatorias → frase | Funciona; ver diceware.dmuth.org |
Diceware es sólido (y diceware.dmuth.org es una implementación excelente que incluso enlaza la viñeta de xkcd en su FAQ). Tales Vault apunta a otro equilibrio: secuencia corta de letras aleatorias (más bits por carácter tecleado) con frases gramaticales que ayudan a recuperarla.
Cómo funciona
[CSPRNG] → contraseña (20 chars, alfabeto del idioma)
↓
bloques de 4: jnra | ngtb | ...
↓
sustantivo + adjetivo + verbo + sustantivo (por bloque)
↓
contraseña + frases + reglas de recuperación
Ejemplo real generado con tale generate --language es:
Password: jnrangtbtljnlbiqnhqm
Mnemonic phrases:
[jnra] jefe nuevo recordar año
[ngtb] noche grande tener bebé
[tljn] tiempo llamado jugar niño
[lbiq] lugar bueno intentar queso
[nhqm] nombre humano querer mujer
Entropy: ~85.0 bits
Cada palabra aporta su inicial normalizada (árbol → a, ñ excluida del alfabeto español). Concatenas las iniciales de cada bloque y recuperas la contraseña.
Principios de diseño
| Principio | Detalle |
|---|---|
| Aleatoriedad primero | La clave nace del generador criptográfico; la frase es derivada, nunca al revés |
| Alfabeto restringido | Las 20 letras iniciales más frecuentes por idioma, maximiza cobertura del diccionario |
| Plantilla fija | sustantivo → adjetivo → verbo → sustantivo por bloque de 4 letras |
| Sin elección de letras | El usuario no inventa iniciales; el TUI solo permite elegir entre palabras válidas |
| Solo minúsculas | Sin Shift ni alternancia de capas; más rápido en móvil y más claro al dictar |
| Local-first | Listas embebidas en el binario (go:embed); sin red en tiempo de ejecución |
| Binario único | ~3 MB con diccionarios EN + ES (~13k palabras curadas) |
El alfabeto restringido reduce algo la entropía por carácter respecto a las 26 minúsculas, pero compensa con longitud: 20 caracteres sobre ~20 letras dan ~85 bits, suficiente para una clave maestra o pocas contraseñas críticas memorizadas.
En español, la distribución desigual de palabras por letra inicial (que en el post anterior explicamos como sesgo humano) aquí se gestiona de forma explícita: el alfabeto se calcula a partir del corpus, y tale stats muestra la cobertura real por letra (a: 360 palabras, q: 48).
Solo minúsculas
Tales Vault genera contraseñas en minúsculas a propósito. Responde a los escenarios donde más duele teclear una clave que memorizas tú.
En el post anterior ya vimos el coste de Shift, símbolos y mayúsculas en teclado físico. Aquí la decisión es de producto:
- Un golpe menos por carácter. Cada mayúscula exige
Shifto cambio de capa. En veinte caracteres, evitar mayúsculas elimina hasta veinte pulsaciones extra y el riesgo de pulsar la tecla equivocada. - Móvil. En pantalla táctil, alternar mayúsculas y minúsculas ralentiza mucho la entrada. Una clave de solo minúsculas se teclea en la capa por defecto, sin saltar entre modos.
- Dictado. Si transmites la contraseña en voz alta (copia de seguridad con alguien de confianza, repaso mientras la memorizas) no tienes que aclarar “ese es mayúscula” ni deletrear con ambigüedad.
jnrangtbtljnlbiqnhqmse lee letra a letra, siempre igual.
La entropía no se sacrifica en vano: el alfabeto tiene ~20 letras y la longitud por defecto es 20 caracteres (~85 bits). Más longitud, un solo caso, compensación deliberada frente a mezclar mayúsculas, números y símbolos que en la práctica nadie teclea bien.
El comando tale
El repositorio publica un binario Go llamado tale. Instalación mínima:
git clone https://github.com/escribanoruben/tale
cd tale
make build # o: go build -o tale ./cmd/tale
Generación automática
./tale generate --language es
./tale generate --language en --length 16
Modo aleatorio completo: contraseña, frases, entropía estimada y reglas de recuperación en stdout. Sin almacenar secretos en disco.
Modo interactivo (TUI)
./tale tui --language es
./tale tui --language en --password abcdefghijklmnopqrst
Interfaz en terminal (Bubble Tea) con selector tipo rodillo: por cada letra del bloque, eliges entre palabras cuya inicial coincide. Útil si quieres una frase más personal sin tocar la entropía de las letras, esas ya están fijadas.
Estadísticas del diccionario
./tale stats
Muestra alfabeto, palabras por letra y parte del discurso. Herramienta de transparencia: puedes verificar que el idioma tiene cobertura antes de confiar en el generador.
Idiomas
| Idioma | Código | Alfabeto (20 letras) |
|---|---|---|
| Inglés | en | abcdefghilmnoprstuvw |
| Español | es | abcdefghijlmnopqrstv |
También admite idiomas personalizados bajo ~/.tale/ (tale language new, tale language init). Los built-in cargan listas embebidas; los custom requieren rellenar los TSV correspondientes.
Local-first y soberanía digital
Las listas de palabras viajan dentro del binario. No hay llamadas a APIs, no hay “genera tu contraseña en la nube”. En un contexto donde mandar secretos a terceros es inaceptable (o simplemente donde quieres auditar qué palabras puede proponer el sistema) eso importa.
En el marco RPS, Tales Vault es piedra pragmática: un binario, cero ceremonia de despliegue, máxima transparencia sobre el diccionario. No pretende ser una plataforma de identidad ni un gestor completo.
Límites honestos
- No sustituye un gestor de contraseñas. Está pensado para pocas claves que memorizas tú.
- Entropía algo menor que 20 minúsculas puras por el alfabeto recortado, documentada en la salida.
- Cobertura del diccionario. Bloques sin candidatas válidas se regeneran; en español algunas letras tienen menos palabras que otras.
- Modo TUI y sesgo. Si eliges siempre la palabra “más bonita” entre candidatas, introduces sesgo en la memorabilidad, no en las letras, pero la frase deja de ser la que el scoring automático habría elegido.
- Licencia del proyecto: TBD en el repositorio; las fuentes de las listas tienen licencias propias (ver
internal/worddata/README.md).
Diceware y diceware.dmuth.org
Antes de hablar de tale, conviene situar Diceware bien hecho. diceware.dmuth.org, de Douglas Muth, es la referencia web que más gente conoce: tiras virtuales de dados, lista de palabras de la EFF, passphrase generada en el navegador sin enviar nada al servidor. Cuatro palabras aleatorias ≈ 44 bits; seis, ≈ 66. Las palabras son la contraseña: las recuerdas y las tecleas tal cual.
Casos donde Diceware brilla (el propio sitio los enumera): Smart TV, teclados incómodos, ordenador ajeno sin gestor instalado. Escribir correct horse battery staple es más lento que veinte letras seguidas, pero cada palabra es un chunk mental reconocible.
Tales Vault System no compete con eso; resuelve otro perfil:
| diceware.dmuth.org | Tales Vault (tale) | |
|---|---|---|
| Qué memorizas | Las palabras aleatorias | Frases mnemotécnicas; la clave son las iniciales |
| Qué tecleas | Palabras completas con espacios (o sin ellos) | Solo minúsculas, sin Shift ni alternar capas |
| Flujo | Palabras aleatorias → passphrase | Letras aleatorias (CSPRNG) → frase derivada |
| Idiomas | Lista EFF en inglés | Inglés y español embebidos; alfabeto por idioma |
| Entorno | Web (JS local) o fuente en GitHub | Binario Go offline (go:embed) |
| Entropía típica | ~44 bits (4 palabras) / ~66 (6) | ~85 bits (20 letras, alfabeto ~20) |
Si quieres passphrase de palabras enteras y te encaja el ritmo de Diceware, usa Diceware (de verdad). Si necesitas más entropía por tecla, solo minúsculas, recuperación por frases con plantilla gramatical y soporte ES nativo, ahí está tale.
Distinción frente a otros enfoques
| Sistema | Quién elige | Entropía |
|---|---|---|
| Tales Vault | CSPRNG → frase derivada | Alta (~85 bits, letras uniformes) |
| Diceware (dmuth.org) | Dados/PRNG → palabras | Alta (~44–66 bits según longitud) |
| Frase memorable | Tú → iniciales | Baja (sesgada) |
| Gestor | CSPRNG → almacenado | Alta (no memorizas) |
Qué viene
En el repositorio hay una discusión de diseño abierta sobre añadir dígitos de control derivados al final de la contraseña, un checksum para detectar errores al recuperar la clave desde las frases (bloque mal ordenado, palabra mal recordada).
El código, las specs OpenSpec y las listas de palabras están en github.com/escribanoruben/tale. Si pruebas tale y encuentras un bloque sin frase válida en tu idioma, abre un issue, las contribuciones al diccionario son bienvenidas.
Cierre
Aleatorio y memorable no son opuestos si el orden es el correcto: primero la entropía, después la historia. El cómic de xkcd lo intuyó; Diceware lo demostró con dados. Tales Vault lo lleva a un flujo reproducible, auditable y local, con un comando que puedes compilar tú mismo.
Para el resto de tus contraseñas, sigue usando el gestor. Para las pocas que necesitas llevar en la cabeza, que al menos las letras no las elija tu intuición.