Nick | OneThingWell.dev
Posted on August 8, 2022
Let's see how we can generate truly random passwords on Linux - first, using only standard tools we already have on the system, then we'll take a look at useful 3rd party tools.
First, we need a good source of randomness. There's an old joke that the best way to generate a truly random string on a Linux box is to put a new user in front of vim or emacs and ask them to exit. /dev/urandom is usually the second-best choice.
/dev/urandom
Basically, /dev/urandom is a special file, which provides us with a stream of random bytes (collected from environmental noise from sources like device drivers).
There's also /dev/random, but it's almost deprecated at this point, there is rarely a good reason to use it nowadays.
If you'd try to read /dev/urandom directly with:
cat /dev/urandom
It would quickly break your terminal with unprintable characters. So, we need a way to limit the set of returned characters.
When you're working with translating or filtering sets of characters, tr
is a very handy tool (and since it's a part of the coreutils
package, you almost certainly already have it on your system).
We can define a set of characters (-c) and delete everything else (-d) like this:
cat /dev/urandom | tr -dc a-zA-Z0-9
Or, to remove the unnecessary use of cat
command:
tr -dc a-zA-Z0-9 </dev/urandom
This works, but it provides us with a continuous stream of characters defined in our charset. Now we just need a way to limit the number of returned characters. We can do that easily with head
command:
tr -dc a-zA-Z0-9 </dev/urandom | head -c 15
head -c
does exactly what we want here: it just returns the first 15 bytes of data from our stream.
And this gives us a random, 15 characters password as expected, e.g.:
0vp3HkQS52xqvuR
This type of password should have enough entropy for most use cases, but if you need more, you can easily include additional characters:
tr -dc 'a-zA-Z0-9_!"#$%&' </dev/urandom | head -c 15
Note: Your terminal may be unhappy about the missing newline character - neither tr
, nor head
adds a newline character (theoretically, we could get it from /dev/urandom, but it will be deleted by tr
). You can fix that easily by adding an empty echo
command afterward:
tr -dc a-zA-Z0-9 </dev/urandom | head -c 15; echo
openssl
If for some reason you can't use /dev/urandom, openssl
can also generate truly random strings.
If you're OK with only characters from base64 charset, you don't need anything other than openssl
:
openssl rand -base64 15
or hex:
openssl rand -hex 15
Otherwise, we can create random bytes with openssl rand
, but since it doesn't support streaming, we need to create enough bytes to filter them afterward:
openssl rand 512 | tr -dc a-zA-Z0-9 | head -c 15
This should give us a very similar result to the previous command with /dev/urandom.
pwgen
Now that you know how to make this yourself, it's worth mentioning pwgen
tool which will create a set of random passwords, but it will try to make them pronounceable and easily memorized by humans.
It's available in the official repositories of most mainstream distributions, and you can install it with something like this:
apt install pwgen
dnf install pwgen
pacman -S pwgen
For example, this will create a set of 20 passwords of 15 characters:
pwgen 15 20
Example result:
zo2aiTaiveey8xi Iephohpiush4Aik Oos4Riekieshohs eisheGheeh4an5y thah1seesho0ooZ
eedeithogaiRa3i Chie9uchaigh3iz aix2Ung2oid2ivi quiavaiMie3Fahv iesho1Kughienai
UuBu4wei0hiuCas jai6OwooniNgahm ieVox0shi3xehoh oo4haaHaijaesh3 eic8aiGohcuyah5
ii5eoDooc8ui6Sh Goohei7ureetu0B ceiB3auK9eiquu0 koSoh7ea6ga7On0 uxeing6dah3haiF
makepasswd
There's also an old tool called makepasswd
, which is similar to pwgen
, but its focus is more on random than pronounceable passwords.
You can install it with something like:
apt install makepasswd
dnf install makepasswd
The problem with makepasswd is that it uses an old /dev/random interface, which can cause blocking issues, especially in environments that don't have an access to a lot of sources of entropy (like VMs).
An equivalent example to the above pwgen command would look like this:
makepasswd --chars=15 --count=20
Example result:
MrIYQswWdFKMbm5
S2QszHCUs1F04Ge
bzpLR4agSpqtIX0
rYw9E2psW8bnwFg
BocTzXeGda54K9i
ELQytdfXDzGGfXR
ufJuUt7d8C2KimN
CKJQos4rIHdAGv4
njTM48Ku2VJXfb9
K3qaP5WGAe6wCcg
ePD6Lr8z0GybYCz
RMrih3WpXxw0RGc
xGVeQGtWn8pq63H
LqvL7MQb8FQabDn
7J7t1Yg0e2whEUH
JuA1WxXRR6XeRPm
sG6oWN8q8SMroz1
Womp56gy0uemUjj
prnbNr5sJGGI1gw
0a6K8oebrBKhBcb
Note: this is a wiki article from BetterWays.dev: Linux by Example series, you can find the latest (better formatted) version here: https://betterways.dev/linux-generating-random-passwords
If you find this type of post interesting, please let me know (with reactions and/or comments).
Posted on August 8, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
January 18, 2021