Tips and Tricks for Password Generation
If you are anything like me, you probably have a lot of different places you need to log in with a username and password. Hopefully you are using a password manager to keep track of all of them so you don’t have to. My preferred option is 1Password; while it’s not free, I have great confidence in their security and for the value I get it’s some of the best money I pay.
For actually generating the passwords, I don’t use 1Password. The passwords it generates don’t seem to have the distribution of characters I would expect from a truly random password. This is probably because many sites actually require at least one uppercase letter, one lowercase letter, one digit, and one symbol, and then often restrict the list of symbols you can choose from, so these restrictions are sensible and prudent given the circumstances. However, I prefer line-noise passwords when possible and will gladly regenerate a password a few times if necessary, so I prefer to do things a little differently.
In all cases, I use a tool I’ve written called muter. It does cryptographic hashing and encoding and decoding of data in various formats, and I find it very convenient because I can just adjust the encoding format based on the password requirements.
If the password doesn’t have any requirements, I pipe in a bunch of random data, hash it with SHA-3-384, and then Ascii85-encode it. That gives me 60 characters, which will work with sites using bcrypt, which limit passwords to 72 characters. 256 bits would be enough, but using a little more allows a part of the password to be exposed accidentally without decreasing security.
If the password has restrictions on special characters, I’ll use the Base64url
encoding (muter’s url64
codec), which only outputs -
and _
. If those
aren’t in the set of special characters, I’ll use tr
to adjust them so that
they are. I will often need to use a shorter hash in these cases, often a
truncated BLAKE2b.
If the password doesn’t allow any special characters, I’ll just use Base32 encoding. At such a point, I generally reconsider whether I really need this account.
In some cases, the password does need to be typed by humans. An example is the password for my Wi-Fi network. Last time I generated it, I picked a 20-character line-noise password, much to my friends' dismay. I recently, in fact, found out that the reason one of my friends couldn’t ever get it right is that he mistook my handwritten semicolon for a lowercase j.
The technique I usually use for human-readable passwords now is the Bubblebabble
encoding. It was originally developed for use with SSH as a way to share
fingerprints, and can be used to encode any string. For example, the encoding
of the word "Pineapple" is xigak-nyryk-humil-bosek-sonax
. The encoding of a
string with 128 bits of entropy is 53 characters, which while not great, is at
least easier to type than a suitable line-noise password.