A few years ago now, I decided I wasn't satisfied with the way I was managing my passwords. Basically, my history in terms of password had started about more than 10 years ago, probably at the time I got my first email address. And as I'm sure pretty much everyone out there, I started with only one password for everything. Then I realized that sometimes it wasn't a great idea for some websites to have the same password as my email password for instance, so I came up with a couple shitty passwords only for websites of no or little importance. But at some point, I realized it was just a big mess: I couldn't always remember what I had registered in the first place, which was forcing me quite often to test my whole collection of passwords to access some website.

Long story short, I decided it'd be nice to have a real password management system.

The basic idea

In the password management spectrum, there is on one end the policy to have one password for everything, which is, needlessly to say, a terrible idea. On the other end, there is the policy of having super strong passwords (more than 8 characters, composed of lower/upper/digit/punctuation characters) that are unique for each service.

I thought the paranoid approach was maybe slightly too paranoid, and also I still like being able to remember some passwords, which turns out being quite difficult when you have a unique and strong password for each service you use.

Therefore, as we say in my native language, I cut the pear in half (compromised) and decided on a system where my passwords can be unique for certain extra sensitive services, such as my computers/servers, emails, etc., or common for groups of less sensitive services. In my configuration, I defined 3 groups: sensitive, important and neutral (i.e. don't care that much). But it'd be possible to define as many categories as you want.

And finally, all those passwords are automatically generated in a deterministic manner, from only one master password. So eventually, you really just have to remember one password to unlock all the others.

Technicalities

Nowadays, depending on the website, passwords are usually composed of four possible classes of characters: lower, upper, digit and punctuation characters. By chance, it's exactly the set of characters that base64 is able to produce.

For generating unique passwords, we will use our master password and the name of the service for which we generate the password and pass it into a hash function. Here I chose sha256 because it's a widely implemented standard, but I guess it could be anything else.

To summarize, the password generation theoretically looks like that:

"my_master_password service_name" -> sha256 -> base64

Quickly I realized there should be a variable part in the input, in case the generated password is compromised and needs to be changed, without changing either the master password nor the service name (which wouldn't make sense). This extra variable token can be pretty anything, but usually for myself I used 4 digits representing the month/year I created the password.

So basically, if today (May 13th, 2014) I decide I want to create a unique password for my ikiwiki account, I would define the input as:

"my_master_password ikiwiki 0514"

And if one day, I think this password has been compromised (because of heartbleed for example), I just need to modify the extra token to generate a completely new password.

First version

The first version of my password manager was a small shell script and a text file. In the text file, I had a list with the services (and optionally the identifier I was using for each service) to remember which service has a unique password and which service belongs to a group. It looked like that (FYI, the following info are completely bogus):

*** Unique passwords ***

ovh 1211        /joel.porquet
columbia 1211   /porquet
lip6 0813       /joel

*** Sensitive group ***
- common1 1211
amazon.com      /joel.porquet@gmail.com
t-mobile.com    /7315957504

*** Important group ***
- common2 0212
airbnb.com      /joel.porquet@gmail.com
linkedin.com    /joel@porquet.org

...

And the script, jpass.sh looked like that:

read -s -p "Enter master pwd: " mpwd
echo ""
read -p "Enter service/date: " serdat
echo -n "$mpwd $serdat" | openssl dgst -sha256 -binary | base64 | head -c 8
echo ""

It wasn't optimal, because each time I needed a password that I couldn't remember, I had to open the text file, copy the service/date token and paste it into the program. Also, the length of passwords was hardcoded to be 8 characters.

The nice version in python

Recently, I started to write a "real" piece of software to manage those passwords. It had been been a while I wanted to learn python, hence the choice of python for this software. It's now a quite stable state and I decided to share it.

More on jpass.