sehrope/node-simple-encryptor

Optional array of decryption/hmac keys

boenrobot opened this issue · 2 comments

I have a lot of pieces of data in a database, each encrypted and decrypted at different times.

Although the encryption key is likely to change rarely, I'd still like the ability to change it out smoothly without having to re-encrypt all of my data at one time, and cause downtime, as database access would have to be blocked while this takes place.

I think the best solution to this problem is to accept an array of keys. Encrypt only with the first, but attempt to decrypt with all, starting from the first, and going down the list, only returning null if all keys fail.

The hmac function should also return hmacs with all provided keys in that case, returned in the same order (so that one can match the key).

Having both of those will allow the relatively smooth migration of old data, where one could re-encrypt it either on modification, or on lookup through the hmac.

The alternative right now would be to have multiple SimpleEncryptor instances, but managing them would be somewhat of a hassle.

Overall I like this idea. Only issue I have is that to maintain backwards compatibility with the existing hmac(...) signature the return type cannot be changed to an array. Similar to encrypt(...), how about having hmac(...) use the first key and a new verifyHmac(...) would be added to try multiple keys and return a boolean if the computed HMAC matches.

I don't think verifyHmac() would work for the scenario I'm talking about...

I mean, the HMAC is stored in the DB next to the encrypted data (or within it... either way...), and then when an authorized person needs to lookup the encrypted data, an HMAC of their input is computed, and that is looked up in the DB table with the HMACs.

So... if I use the hmac() from the encryption with the latest key, I just won't get any matches, so there's no way to know that there IS a match in the current data in the DB, but that it is old and needs to be re-encrypted.

If I was to instead search for multiple HMACs - one for each encryption key - and find a match with an hmac that is not the first, I will know that this other match likely needs re-encrypting, and I'll do so right there. The rare case of "an actual HMAC with the latest key, but for a different input" can be avoided by comparing the decrypted data with the input, and not re-encrypt it if it's different.

Anyhow... I get your point about having a different signature... a new method that returns an array of hmacs, while the current one returns just for the encryption key would also work fine I think. Or perhaps an argument to the hmac() method that defaults to the current behaviour (the TS definition can use a overload).