I'm creating an application which generates licenses key and stores this in a database (the licenses are checked online). I don't wish to store these license unhashed, in case the database is stolen.

However, once the license key is hashed (with salt), it becomes very difficult to check if a given key exists in the database, since the salt used will change with each key.

What is the best solution to be able to find and verify a hashed license key? I have considered hashing half of the license key unsalted, and using that to identify the license row before checking the full key hashed with salt. Is this too risky?

I've also considered using the last 1/4 of the key as an identifier (e.g. AAAB = 1, AAAC =2 etc), For a key length of 16, this allows 2^20 keys.

(Side note: keys are base32 encoded, and will be 16 characters long (but could be chosen longer). The application is a general one - i.e. it's not tied to any particular use-case, so there is no fixed estimate on the number of licenses required - although the key length could be increased depending on that esimate).

1 Answer
1

However, once the license key is hashed (with salt) - it becomes very difficult to check if a given key exists in the database - since the salt used will change with each key.

Salts are designed to be used when you already have an identifier to look up the corresponding hashed field. For example, you don't look to see if "password" exists in any of the password fields, but rather that for "user" the password is "password".

If you're going to salt your passwords (licenses), then you need to assign a unique identifier to it which is stored without any hashing.

Prepend a unique ID of a fixed width to the first bytes of your licenses or use a delimiter and split the ID off before hashing on the server.

Thanks Jeff, I thought as much. I'm decided to convert the database ID into an identifier (with charaters A-Z,2-7) as above, and append this to the key. It is padded, when necessary, to be 1/4 of the key length for scalabilty.
–
Stephen HarrisOct 2 '12 at 10:41