This program implements the basic idea behind scrypt, as seen in slide 11 of the scrypt PDF.
First, create a file called hap2.sitelist
in ~/.config
.
We will use the following example all through, so put the following text into that file:
# nick user salt site check len suffix
test alice 2 foo.com DGvU 10 !
To compute the password for this test site, just run hap2 test
.
Hap2 will ask for a master passphrase. Type in your master passphrase. At this point you wait for a while and it prints you the computed password.
If you don't have your sitelist file handy, but you are on a machine you trust, and you remember the details of the site for which you need the password, you can just get the hap2 script and run a command like this:
hap2 sitaramc 1 gmail.com
It'll prompt you for the master passphrase and once you type that you get your password.
Currently, the sitelist file is hardcoded to ~/.config/hap2.sitelist
,
although of course you can make that a symlink to something else.
Hap2 only reads this file. There is no GUI to edit it, but a very good gui program that I have found very useful can be found here.
The rules for the file are:
- A line consists of multiple space-separated words. The number of spaces doesn't matter.
- The first word in the line is a "site nickname".
- The next 3 fields (user, salt, site) are required.
- The last 3 (check, len, suffix) are optional, but the field order is fixed, so (for example) you cannot supply a "len" value without also supplying a "check" value.
- comment lines are allowed
As you know, hap2 basically computes something from a given input string,
which is created by combining the user, salt, and site strings. In our
example, it will be alice+2@foo.com
.
The salt field needs some explanation. This field is mainly used when you need to change the password for a site, for whatever reason. Just put something different in the salt field, and you get a different password.
Typical values for salt are the date of the password reset (2013-06, or 2013-06-23, etc.) or a number that is incremented by 1 each time you change the password (1, 2, ...).
IMPORTANT: you will need to remember this "salt", although it need not be kept secret. In other words, BACKUP YOUR SITELIST FILE!!. (See TODO list for more).
During the initial days of testing, I used to worry that if I ever mis-typed the master passphrase, of if hap2 ever had a bug, I'd never know, and I'd keep trying with the password, and probably get locked out if the website has a limit on that or something.
That led to the 'check' idea. When the sitelist file does not have a 'check' field for the site, then hap2 generates a 'check' value. It then prompts you to add this line to the sitelist file, so that future runs of hap2 for that nickname can check if the correct password was generated.
Don't forget to update this if you change the salt, though! To compute the new 'check' value, just delete the 'check' field (and, unfortunately because of the rigid format, the 'len' and 'suffix' fields also) and run hap2 again. It will show you what the check value should be, and you can then add it (and add back the other two fields if they were removed).
The 'len' field says where to truncate the output, for sites that don't like overly long passwords (yes, some sites have this stupid restriction, which makes no sense to me!).
Note that if a "suffix" (see later) is specified, the suffix value is added after the "len" truncation, so then the final password will be a bit longer.
Also note that any site which restricts passwords to below 12 characters in length should be avoided. If you can't avoid it, at least name and shame it!
Some sites have stupid requirements like "at least one uppercase, one special character, ..." and so on. If the password generated by hap2 does not meet the criteria, you can specify a suffix that will get tacked on to the end.
I considered specifying all the requirements, then writing code to analyse the generated password and morph it to meet those requirements, but it didn't seem worth the effort.
I am only interested in the basic idea from scrypt, and to implement something that is close enough using perl and commonly installed perl modules. I don't need it to be exactly the same.
For example, I use HMACSHA2 instead of PBKDF2. In fact, since I have looked at neither the full scrypt paper, nor the source code for scrypt, there are probably several other differences.
It also doesn't have any of the time/memory constraint settings that the original scrypt program has. We just use a hardcoded 1 million rounds for now. (Again, see TODO list for more).