HOWTO: Password generation in the GNU/Linux CLI

FROM: UNIX COMMAND LINE WORKSHOP
SKILL LEVEL: FIT

Generating passwords in the GNU/Linux CLI

apg, the Automatic Password Generator

apg is a respected CLI password generator for UNIX systems, favoured in that it generates provably strong passwords with the advantage of providing the user with phonemes to assist memory. It uses /dev/random as the initial random seed. using

The point of introducing phonemes (here, the FIPS-181 NIST Implementation) is that less memorable
passwords of the same or even longer length are (counter-intuitively) often /more/ vulnerable than shorter, more memorable strong passwords.

Why is this?

  • They’re readily forgotten and so requested back over the wire

  • People tend to write them down on computers and objects

  • Others tend to use password-managers that (unlike keepass) are often very dubious

  • Hard to remember passwords are often rotated/changed less regularly, because of users are reluctant to go through the challenge of remembering a new one over and over.

Basic apg useage

Creating memorable, strong (for their length) and web-safe alphanumeric passwords is easy with apg.

julian@zeppelin:~$ apg
Please enter some random data (only first 16 are significant)
(eg. your old password):>
VagjanVeit0 (Vag-jan-Veit-ZERO)
CymyudJab3 (Cym-yud-Jab-THREE)
doshawAft7 (dosh-aw-Aft-SEVEN)
rew8griOg7 (rew-EIGHT-gri-Og-SEVEN)
EvNagsebJor1 (Ev-Nags-eb-Jor-ONE)
UlCizIcpeps5 (Ul-Ciz-Ic-peps-FIVE)

apg can also be used to generate non web-safe passwords, the kind that no human
can readily remember:

julian@zeppelin:~$ apg -s -a 1 -m 63 -n 6

Please enter some random data (only first 16 are significant)
(eg. your old password):>
MB|YAx)hC#j.5v#%FZQtYQncl<&%`Dw\RGfeChJ9y*Wy3'b`LGuQ`mr*lojjNnB
H%}P)csL)pg``Ezu6Me-57);9$m4+8Vc,j2fz~`Z8-0-15=no."MCI]1r<~Bj.E
e7\R~T:L-rTI*(q"kme]'OQqAC]caGcH#lx(&9{.\f(K)!O?8KO0yhrfFnc_zxp
@8Z|{tg(bKe`*FLO6]*0.c(G+dI8(S2[&ExPqn<lGf}[|zNHoW5SM#~'YZH-&\,
d\#zRe?77$KMv;^(Gl>JD*",T\p(Ho'|hUl>$}:'a)4(4.$njY@vMX_5v:}yf1`
P5,UKPCwLD#AmKau*!e,3!2m1~LD+cR9j4Y\]Q9.AHW<vznnZbw(J4Mj6gk|#,d

Alternative methods

An alternative means of generating similar passwords to *apg’*s default mode, but without the advantage of memory aids, might be:

julian@zeppelin:~$ < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-12};echo;
J9wkdNsa3lyJ

You could also just:

julian@zeppelin:~$ date | md5sum
f3fa14f183604d9d9b318d9f7178e29e  -

Or longer:

julian@zeppelin:~$ date | sha256sum
a8969c7fce131787cb4dd7ea773b02422916c739517208a75f42d30de455620a  -

NOTE: these two methods are insecure on their own. Use with a bit of salt or just use 16+ chars of it, move chunks around, etc.

Updated Feb 13, 2016


Good stuff, I wish sha1 and md5 methods would produce more variation in character range and not just HEX.
Here is something very quick:

head -n10 /dev/urandom | strings | tr -d [:space:][:punct:] | cut -c -10
jKBaOq9Fv7

where the last number defines desired length of the password.

Danja

and this one wins the prize!

head -c12 /dev/urandom | base64
tFUA93Z4p0wj3pBC

by @dchest

This topic is now pinned. It will appear at the top of its category until it is either unpinned by a moderator, or the Clear Pin button is pressed.

By the way, Julian’s Alternative method #1 works in zsh only. Here is a version that works in any Bourne-style shell including dash, bash and zsh:

tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 12; echo

The date trick is intriguing, but if called more than once per second, it will produce the same result. This could be avoided by including nanoseconds like this:

date +%s%N | sha256sum

Actually, I like Danja’s base64 method best, but note that for the small amount of data required here, you can probably afford to use the higher quality /dev/random instead of /dev/urandom:

head -c12 /dev/random | base64

Great comments and good point about the date period issue. Funny. Admittedly here I don’t need zsh to use the alternative method #1 I cited. On three different GNU/Linux distributions here currently:

$ echo $SHELL
/bin/bash
$ < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-12};echo
a9i_6zyseVPE

Using date for password generation is a really bad idea, at least without a salt.

Instead of

`date | sha256sum`

you could do

`echo "$(date)yoursalthere" | sha256sum`

or you could use date’s formatting to make it a bit more unique:

`date +"%Y-%m-%dyoursalthere" | sha256`

Or you could just use a real password generating program such as pwgen. It will use more printable characters than what you will get with hashes or base64 encoding.

Jon Kulp’s idea for password managing is pretty neat.
In short, he uses pwgen to generate cards like this

oqu9le9ahv7ub6ohthoo2ifee2zei1uX1Pip_ae2oow8lie3Hu
AhfoChomai1wuNg,ie2sae2aep0hohW1quu0nae[ch&ohshi1O
rah7ooMaeneixah'baoboo3eiP9peeteeyai|v8shulahg2jah
eji^ngaezah`gh`eehi5gaTi7Eg2xabaiQuai>leit@ah1Gie`
Eiveebohxahhaiy7airee|V4ay5hahju.thoh4tuJ1OhL3yaez
phoova`chi:oxi"i0biex#iePh6wo5You0Iey5thoo.PieJahT

Then he reads it in random ways. I’ve been using this method for a while now and it has made me use considerably longer passwords and encouraged me to change them more often as it’s pretty much impossible to forget them. There are so many ways to read the card that even if someone sees it they will never guess your password. If you’re really paranoid you can generate new card when someone sees it, but even then you don’t really have to hurry because it would take a heck of a long time to try all the possible passowords in the card even with really powerfull cluster.

Agreed you wouldn’t use all of the date string output for anything serious. Just grab a chunk of it and/or salt it. Ammended post to make that clear.

I like pwgen also.

I still have this randstr() function in my Zshell configuration, although I hardly use it anymore:

# Generate a random string (defaults to ~256bits of entropy)
randstr() {
    emulate -L zsh
    setopt braceccl

    local -i i=0 length=${1:-42}
    local -a pool
             pool=({a-zA-Z0-9^\$\;\,.+=_[]-})
    local    s=""

    RANDOM=$(head -c 256 /dev/urandom | tr -Cd '0-9') # Seed random
    while (( $#s < $length )) ; do i=$(( ($#pool * $RANDOM) / 32767 )); s+=$pool[$i]; done
    print $s
}

Now I’m primarily using pass which is very useful, as it keeps passwords in encrypted files, and has a generate command. I regularly hit bugs, but it’s still an improvement over my previous encrypted Org file.