Generating Random Passwords - Linux by Example
Tags: linux, tutorial, beginners, devops
Published: 2022-08-08 13:25:00

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
```

---
<small>
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<br><br>If you find this type of post interesting, please let me know (with reactions and/or comments).
</small>