Dexie.js: encrypted database

Created on 24 May 2016  路  9Comments  路  Source: dfahlander/Dexie.js

Would it be possible to have a encrypted indexedDB that can only be read/write and searchable by a web crypto key?
Database name, Table names, rows, indexes, (everything) encrypted so it can not be read by an attack

idea

Most helpful comment

Yes, it may be something to accomplish with an addon. Even though only the equals() and anyOf() queries would give any valid results in those cases. Also need to let this addon intercept the WhereClase methods as well as Table.get() and register all four CRUD hooks. But it's possible.

Would also need to define the API for how to mark a table or selected properties as encrypted. Need to be able to encrypt either indexed or non-indexed properties or the entire table.

Then would need a 'keyneeded' event wich a flag whether it's for creating the table or for querying it. This event would expect its subscriber to return a promise providing the encryption key. Finally, a resetEncryptionKey() method that clears all encrypted tables and resets the key.

All 9 comments

I use encryption in my app but to the cost of lesser indexing capability. You can index a HMAC-Sha digest of the value. The HMAC-Sha is a hash algorithm that also takes an encryption key. To get the correct digest 媒ou must know the value and the key. But it wont work with ranges or substring matches - just exact matches.

Example:

var KEY = "secret"; // Have somewhere in a module or so.

function encrypt(obj, key) {
    // TODO implement using webCrypto or similar
}

function hmacSHA(prop, key) {
    // TODO implement using webCrypto or similar
}

function User(name, age) {
    this.data = encrypt({name: name, age: age}, KEY); 
    this.nameIndex = hmacSHA(name, KEY);
}

// Store user
db.users.put(new User("Foo", 42));
// Find user by name. Need to know the exact name:
var user = yield db.users.where('nameIndex').equals(hmacSHA("Foo", KEY)).first();

Note though, that the index can make the data subject to replay attacks, so if you should be able to index the data you will loose some security value. But sometimes you need to take the least bad of two things...

For example, even without the key, it would be possible to see if two users have the same name. You can't know the name but the index is the same. Also, if an attacker has extremely good hardware and knows a name of a particular user, she could brute force attack the database to find out the key. That would require lots and lots of hardware if key is 128 bit, if at all possible. But in theory, with government hardware, it could be.

It would be cool to have some authentication in the beginning when you open the database with dexie that whenever you put something in the database it will be encrypted for you, same thing when you query the data, but decrypt

That would truly make dexie unik as having client side storage encryption.
The usecase would be to handle multiple accounts on the same browser but don't want to flush the database because someone else logs in

Yes, it may be something to accomplish with an addon. Even though only the equals() and anyOf() queries would give any valid results in those cases. Also need to let this addon intercept the WhereClase methods as well as Table.get() and register all four CRUD hooks. But it's possible.

Would also need to define the API for how to mark a table or selected properties as encrypted. Need to be able to encrypt either indexed or non-indexed properties or the entire table.

Then would need a 'keyneeded' event wich a flag whether it's for creating the table or for querying it. This event would expect its subscriber to return a promise providing the encryption key. Finally, a resetEncryptionKey() method that clears all encrypted tables and resets the key.

Cool!
I was thinking if there would be anyway to have the database searchable... But i guess you would have to decrypt the hole database first then and have it in the RAM. Perhaps not that efficient... best would maybe to do it yourself somehow, getAll() then filter or use the iterator until you find what you are looking for

It could be searchable but only by exact match if using hashed indexes with a salt, such as HMAC-SHA.

I'm using Dexie and am looking into Encryption. I just saw that YDN-DB supports record encryption. Looks like they use salt to protect against the attack mentioned above.

The only thing that can make encrypted data indexable is either 1) to index a digest (preferably salted), 2) index the encrypted content but skip the random IV (symmetric encryption) or 3) to use assymetric encryption with fixed padding instead of random. Salting a digest will at least avoid brute force attacks of publicly known digests but it doesn't protect from being able to see patterns in the encrypted data (several records with same digest indicates they have something in common). In all three cases you will only be able to match by exact value (not between, below or above). Also, in all three cases, the security level of the encryption will never be as strong as properly encrypted data with random IV's or padding.

An add-on for encryption is now available: dexie-encryped

npm: https://www.npmjs.com/package/dexie-encrypted
github: https://github.com/mark43/dexie-encrypted

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Script47 picture Script47  路  3Comments

devolarium picture devolarium  路  3Comments

xavibonell picture xavibonell  路  4Comments

fulltic picture fulltic  路  4Comments

Script47 picture Script47  路  3Comments