9 min read
Tales Vault System: random first, memorable second

In the previous post we saw that entropy only matters when randomness is real. A password manager solves 99% of cases. But for the master password, laptop boot, or the few passwords you need to memorize without a sticky note, the question remains: how do you generate entropy without falling into the bias of picking words that “sound good”?

Tales Vault System (the tale repository) inverts the usual flow. Password first (CSPRNG). Mnemonic story second, derived with fixed rules. You do not choose the letters; in interactive mode you only pick among valid word candidates if you want to customize the phrase.

The problem a manager does not solve

A manager stores a hundred passwords. But someone has to remember the key that unlocks the manager. And sometimes you must type a password in an environment where pasting from the clipboard is not an option.

Common solutions fail for the same reason:

ApproachFlowProblem
”My favorite phrase”Phrase → passwordHuman patterns, low entropy
LeetspeakWord + substitutionsModern cracking anticipates it
xkcd without diceFour words you pickSkewed distribution by initial letter
DicewareRandom words → phraseWorks; see diceware.dmuth.org

Diceware is solid (and diceware.dmuth.org is an excellent implementation that even links the xkcd strip in its FAQ). Tales Vault targets a different balance: a short random letter sequence (more bits per typed character) with grammatical phrases to recover it.

How it works

[CSPRNG] → password (20 chars, language alphabet)

         blocks of 4: jnra | ngtb | ...

    noun + adjective + verb + noun (per block)

    password + phrases + recovery rules

Real example from tale generate --language en:

Password: pwtiscdobsonvdpnudwt

Mnemonic phrases:
  [pwti] people whole take information
  [scdo] state certain did order
  [bson] book such obtained new
  [vdpn] value different put number
  [udwt] use due was time

Entropy: ~85.0 bits

Each word contributes its normalized initial (árbola in Spanish profiles; ñ excluded from the Spanish alphabet). Concatenate initials per block and you recover the password.

Design principles

PrincipleDetail
Randomness firstThe key comes from a cryptographic generator; the phrase is derived, never the reverse
Restricted alphabetTop 20 most frequent word-initial letters per language, maximizes dictionary coverage
Fixed templatenoun → adjective → verb → noun per 4-letter block
No letter pickingThe user does not invent initials; the TUI only allows choosing among valid words
Lowercase onlyNo Shift or layer switching; faster on mobile and clearer when dictating
Local-firstWord lists embedded in the binary (go:embed); no network at runtime
Single binary~3 MB with curated EN + ES dictionaries (~13k words)

The restricted alphabet slightly reduces per-character entropy versus 26 lowercase letters, but length compensates: 20 characters over ~20 letters yield ~85 bits, enough for a master password or a few critical memorized passwords.

In Spanish, the uneven distribution of words by initial letter (which we described as human bias in the previous post) is handled explicitly here: the alphabet is computed from the corpus, and tale stats shows real coverage per letter (a: 360 words, q: 48).

Lowercase only

Tales Vault generates passwords in lowercase on purpose. It targets the scenarios where typing a memorized key hurts most.

In the previous post we already covered the cost of Shift, symbols, and uppercase on a physical keyboard. Here the decision is product-level:

  • One fewer keystroke per character. Each uppercase letter needs Shift or a layer change. Over twenty characters, avoiding uppercase removes up to twenty extra presses and the risk of hitting the wrong key.
  • Mobile. On a touch screen, switching between upper- and lowercase slows entry a lot. An all-lowercase key stays on the default layer with no mode hopping.
  • Dictation. If you say the password out loud (backup with someone you trust, rehearsal while memorizing) you do not need to clarify “that’s uppercase” or spell with ambiguity. jnrangtbtljnlbiqnhqm is read letter by letter, always the same.

Entropy is not wasted: the alphabet has ~20 letters and the default length is 20 characters (~85 bits). More length, one case, a deliberate trade-off versus mixing uppercase, digits, and symbols that nobody actually types well in practice.

The tale command

The repository ships a Go binary named tale. Minimal install:

git clone https://github.com/escribanoruben/tale
cd tale
make build    # or: go build -o tale ./cmd/tale

Automatic generation

./tale generate --language es
./tale generate --language en --length 16

Full random mode: password, phrases, estimated entropy, and recovery rules on stdout. No secrets stored to disk by default.

Interactive mode (TUI)

./tale tui --language es
./tale tui --language en --password abcdefghijklmnopqrst

Terminal UI (Bubble Tea) with a roller-style picker: for each letter in a block, you choose among words whose initial matches. Useful if you want a more personal phrase without touching letter entropy, those are already fixed.

Dictionary statistics

./tale stats

Shows alphabet, words per letter, and part of speech. A transparency tool: verify language coverage before trusting the generator.

Languages

LanguageCodeAlphabet (20 letters)
Englishenabcdefghilmnoprstuvw
Spanishesabcdefghijlmnopqrstv

Custom languages under ~/.tale/ are also supported (tale language new, tale language init). Built-ins load embedded lists; custom ones require filling the corresponding TSV files.

Local-first and digital sovereignty

Word lists travel inside the binary. No API calls, no “generate your password in the cloud.” In contexts where sending secrets to third parties is unacceptable (or when you simply want to audit which words the system can propose) that matters.

In the RPS framework, Tales Vault is pragmatic stone: one binary, zero deployment ceremony, maximum transparency over the dictionary. It does not pretend to be an identity platform or a full manager.

Honest limits

  • Does not replace a password manager. It is meant for a few passwords you memorize yourself.
  • Slightly lower entropy than 20 pure lowercase letters due to the trimmed alphabet, documented in the output.
  • Dictionary coverage. Blocks without valid candidates are regenerated; in Spanish some letters have fewer words than others.
  • TUI mode and bias. If you always pick the “prettiest” word among candidates, you introduce bias in memorability, not in the letters, but the phrase is no longer the one automatic scoring would have chosen.
  • Project license: TBD in the repository; word list sources have their own licenses (see internal/worddata/README.md).

Diceware and diceware.dmuth.org

Before talking about tale, Diceware done right deserves its place. diceware.dmuth.org, by Douglas Muth, is the web reference most people know: virtual dice rolls, EFF word list, passphrase generated in the browser without sending anything to a server. Four random words ≈ 44 bits; six ≈ 66. The words are the password: you remember them and type them as-is.

Cases where Diceware shines (the site lists them): smart TVs, awkward keyboards, someone else’s machine without a manager installed. Typing correct horse battery staple is slower than twenty letters in a row, but each word is a recognizable mental chunk.

Tales Vault System does not compete with that; it solves a different profile:

diceware.dmuth.orgTales Vault (tale)
What you memorizeThe random wordsMnemonic phrases; the key is the initials
What you typeFull words with spaces (or without)Lowercase only, no Shift or layer switching
FlowRandom words → passphraseRandom letters (CSPRNG) → derived phrase
LanguagesEFF list in EnglishEmbedded English and Spanish; alphabet per language
RuntimeWeb (local JS) or source on GitHubOffline Go binary (go:embed)
Typical entropy~44 bits (4 words) / ~66 (6)~85 bits (20 letters, ~20-letter alphabet)

If you want a whole-word passphrase and Diceware’s rhythm suits you, use Diceware (for real). If you need more entropy per keystroke, lowercase only, recovery via templated phrases, and native Spanish support, that is what tale is for.

How it compares

SystemWho choosesEntropy
Tales VaultCSPRNG → derived phraseHigh (~85 bits, uniform letters)
Diceware (dmuth.org)Dice/PRNG → wordsHigh (~44–66 bits by length)
Memorable phraseYou → initialsLow (skewed)
ManagerCSPRNG → storedHigh (you do not memorize)

What’s next

The repository has an open design discussion on adding derived control digits at the end of the password, a checksum to detect errors when recovering the key from phrases (wrong block order, misremembered word).

Code, OpenSpec specs, and word lists live at github.com/escribanoruben/tale. If you try tale and hit a block with no valid phrase in your language, open an issue, dictionary contributions are welcome.

Closing

Random and memorable are not opposites if the order is right: entropy first, story second. The xkcd comic intuited it; Diceware proved it with dice. Tales Vault brings it to a reproducible, auditable, local flow, with a command you can build yourself.

For everything else, keep using your manager. For the few passwords you need in your head, at least let the letters be chosen by something other than your intuition.

Comments