Linux: Generating Random Passwords📄 BetterWays.dev wiki page | 🕑 Last updated: Aug 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.
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:
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
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
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.:
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
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
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 rand -base64 15
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.
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
zo2aiTaiveey8xi Iephohpiush4Aik Oos4Riekieshohs eisheGheeh4an5y thah1seesho0ooZ eedeithogaiRa3i Chie9uchaigh3iz aix2Ung2oid2ivi quiavaiMie3Fahv iesho1Kughienai UuBu4wei0hiuCas jai6OwooniNgahm ieVox0shi3xehoh oo4haaHaijaesh3 eic8aiGohcuyah5 ii5eoDooc8ui6Sh Goohei7ureetu0B ceiB3auK9eiquu0 koSoh7ea6ga7On0 uxeing6dah3haiF
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
MrIYQswWdFKMbm5 S2QszHCUs1F04Ge bzpLR4agSpqtIX0 rYw9E2psW8bnwFg BocTzXeGda54K9i ELQytdfXDzGGfXR ufJuUt7d8C2KimN CKJQos4rIHdAGv4 njTM48Ku2VJXfb9 K3qaP5WGAe6wCcg ePD6Lr8z0GybYCz RMrih3WpXxw0RGc xGVeQGtWn8pq63H LqvL7MQb8FQabDn 7J7t1Yg0e2whEUH JuA1WxXRR6XeRPm sG6oWN8q8SMroz1 Womp56gy0uemUjj prnbNr5sJGGI1gw 0a6K8oebrBKhBcb