Wednesday 2 August 2017

Password manager

We all have a zillion usernames and passwords to remember, and the web sites' requirements to have at least 8 characters, some upper and some lower case, some numberic and some miscellaneous characters, make it impossible for anyone except Mr Memory to remember all these. And I'm Mr Goldfish.

The web sites don't make is any easier, either. Some require you to change your password every few weeks, most of them don't echo the password that you type in, and some won't let you cut-and-paste a password.

So many people use a password manager. Which sounds like a good idea, so I looked into it.

A lot of them thought it would be a jolly good idea if I kept my usernames and passwords on their server. No thanks. The rest would let me store MY data on MY computer, but I could only take their word for it that they weren't also taking a copy.

For example, OneLogin had a data breach, and anyone using it was advised to change all their passwords; for me that wuold be *hundreds*. Ugh.

For example, LastPass had a data breach.

So what is the Wise Virgin supposed to do to store her precious oil?

I don't know. It's a problem.

BUT! Every problem is an opportunity seen from the wrong end. So, I thought, I'll write my own password manager. What could be easier?

And actually, it was easy. I wrote it in perl, and I used the Crypt::CBC library.

I started off with a simple plain text file that looked like this:|user1|pass1||user2|pass2||user3|pass3|

So that's a domain name for the web site I'll be accessing, the username, the password, and the email address I gave them when I signed up. Because I give many different email addresses, all of which arrive at my mailbox eventually, but it means I can immediately tell if the email address I gave to Honest Joe has been sold on to Crooked Hilary.

To tell perl that I'm using the CBC stuff, I put near the start of the program:

use Crypt::CBC;

And now I can use Blowfish (or various other ciphers) without me having to get into the messy details of implementing the crypto.

Here's the code to encrypt that file:

sub encipherfile {
$cipher = Crypt::CBC -> new ( -key  =>'I'm not going to tell you the password'
                              -cipher =>  'Blowfish'
open KEYS, '>passwordfile.dat';
open PLAIN, 'plain.txt';
$/ = undef; # this tell it to read the entire file with a single read
$plaintext = <PLAIN>;
close PLAIN;
$ciphertext = $cipher->encrypt($plaintext);
print KEYS $ciphertext;
close KEYS;

That converted the plain text file into a file encrypted with Blowfish (which is considered to be a lot stronger than DES, and is currently fashionable, but I could easily change the algorithm if necessary one day).

The decryption code is very similar.

 sub decipher {
 $decipher = Crypt::CBC -> new (-key =>'I'm not going to tell you the password'
                                -cipher =>  'Blowfish'
open KEYS, 'passwordfile.dat';
$/ = undef;
$ciphertext = <KEYS>;
$plaintext = $decipher->decrypt($ciphertext);


Then I wrote a little cgi, that does a display like this:

And, of course, this is in a password-protected directory, using the usual apache access control system.

So I can add to the database with this form, or I can list all the records, or I can search for the domain name I want the username and password for. And it returns with a little table showing any matches.

It took me a couple of hours to write, and now I not only have a password manager that I know I can trust, but also if I think of any useful features, I can add them.


  1. That's cool. If I had time to learn at the moment I would write one also.
    I have only ever trusted two commercial password managers; Blackberry password keeper and Zoho Vault (for teams). Vault has features to give explicit permissions over shared passwords to groups / individuals.
    Maybe that's a feature for a 'family' pwd mgr - like sharing the Netflix a/c details...

  2. Because I've got it behind an apache access control system, I have to log in to it using a username and password. That also means that the cgi knows which username is logging in, so I could give partial access to the passwords to other people. But I'm not planning to - I wrote this just for me.