Pro heslo délky n, k povinných (disjunktních) skupin znaků:
n-k krát vyber náhodný znak ze sjednocení skupin, lep je za sebe do stringu
Pro každou skupinu vyber náhodného zástupce a dej ho na náhodné místo v řetězci. (Případně dávej na konec a na konci proveď shuffle.)
Není to dokonalé, ale je to na pár řádků (v rozumném programovacím jazyce, v shellu by to byl opruz) a není problém to udělat pro daný seed a offset deterministické.
Jak velice špatný nápad je:
echo $RANDOM$RANDOM$RANDOM$RANDOM$RANDOM
ano, systematicky takto generovat hesla je zlé. Ale pro ručně generované heslo je to ihmo dostatečné, nebo ne? Jak zde zneužít špatný zdroj náhody? Je $RANDOM inicializován nějakým časovým údajem (k prolomení by stačilo projít všechny nedávné sekundy, které to kohly inicializovat)?
To záleží. Co když bude útočník znát čas nastavení hesla (což někdy může, aspoň přibližně), pak by to nemuselo být až tak těžké. Záleží taky na kontrétním RNG apod.
Ale: má smysl to řešit, když použít CSRNG (např. head -c16 /dev/random | base64) není až tak těžké.
(Ano, dá se diskutovat o random vs. urandom. Ale ve chvíli, kdy mám haveged, je obojí dostatečně rychlé.)