Can I use SQLCipher with Ionic "Storage"?


#1

I have an Ionic3 app using “Storage” to create & access an offline SQLite database.
Now I have a requirement to encrypt the database (or else the data that goes into it, which seems like more hassle).

SQLCipher seems to be the sole ‘off-the-shelf’ solution for on-device SQLite encryption. It works with the Cordova ‘SQLite’ plugin though, and I used Ionic’s “Storage” instead.

Could SQLCipher also work with Ionic Storage? How?
If not, why not, and anyone have resources to help switch from Storage to using the SQLite plugin (and to learn the SQLite plugin?) instead?

Thanks for any info!


#2

Can you please explain the purpose of this requirement in terms of:

  • what specific attack(s) you are concerned with
  • what you are willing to require your users to do (such as “enter a password every time they open the app”)

#3

Need to meet a legal requirement to encrypt sensitive personal information in reports that are on a device in case it’s lost/stolen.

The app is often used in areas w/o connectivity, and needs to store info until back in cell range to upload to a server via https, at which point those particular reports could be deleted from the device.

Users could maybe enter a pin or password with each use, or perhaps only when saving a report w/sensitive info (which is a smaller subset of users/use cases). The difficulty here is the lack of internet connection most of the time, so they can’t authenticate w/a server on each use. I’d rather not have to store a pin, key, etc with the app, but haven’t yet figured out what approach might be best.


#4

Very well described. Please see this post. The fundamental concept of KDFs is that you are improving entropy. You can ephemerally store the AES key in a service provider and still use ionic-storage. What I would do is to store opaque encrypted strings in ionic-storage, and have the provider handle the decryption.


#5

@rapropos - Thanks for the reply.

Sorry, this crypto stuff is all quite new to me. I understand the ‘why’ and some of the ‘what’ to use, but I’m not clear how to go about including scrypt (or alternatives) in my Ionic app, or where the various processes happen. (Plenty of recommendations out there for what library or algorithms to use, but less clear info on how).

To clarify what I need to do:
New “secret stuff” is only created in the app, offline.
I need to encrypt (somehow) to store it on the device w/o any access to a server (and even if I had server access, I still wouldn’t be clear on that process …). I need to decrypt it at least on the server, and potentially to view it on the device.

Can you help w/a basic “for dummies” breakdown of what happens where, when & how?

I would use scrypt to create a (symmetric, AES?) key from a password, but where? If created on server (ours is .NET, not Linux btw), the classic problem of how do I get/store the key into the offline app w/o compromising it? Or do I create it in the app & need to store it somehow?

Then what do I use to actually encrypt/decrypt the text content I need to protect, which would use the key from scrypt?

Since AES is symmetric, I shouldn’t store that key with the app, correct?
As you said “ephemerally” … But does that mean I’d need a new key for every use?
In that case I don’t understand how I could decrypt stuff either on device or on the server later w/o keeping a bunch of keys. I don’t follow the basic process.

And presumably I’d need the same key(s) on the server to decrypt content once it’s synced to the remote database? So again how to share/distribute securely?

I see this version of scrypt for npm/JS, which isn’t an ‘official’ release (If there’s a way to run a Linux program from within an Ionic app, I’d love to hear it!). I assume I could install that in my app like any npm module, and use it on-device to create a key from a password … But obviously I have no idea what I’m doing, so …

Sorry for all the follow-up. I don’t know an HMAC from Mac & Cheese, so I could use a bit more basic detail if you have time … Thanks for any further help!!


#6

That is exactly the job of KDFs like scrypt: they turn the password into the key. So on the server, you derive the key from the password, do the encryption, store the encrypted asset in the app. The first time the app is run, the user is prompted for the password, scrypt is run again (on the device this time), and if the password is right, it will come up with the right key.

I would use AES/GCM.

Right.

Not unless you change the password.

The password becomes the key.

The implementation I have used in Ionic apps is scrypt-async.


#7

Sorry, thanks for the clarification, but this still doesn’t make sense to me.

I’m not trying to encrypt content from the server to store in the app.
The content doesn’t exist yet.

I need to securely store new reports created on the offline device, until they’re synced to the server.

I can either:
a) somehow encrypt & then store the encrypted report, or
b) store new reports in plain text (as I’m doing now) & encrypt the entire database, allowing access upon app start with a password (SQLCipher’s approach, I think).

Exactly how to ‘do the encryption’ on the device, or how to encrypt the SQLite storage itself is what I’m trying to figure out.

What crypto library exists to use AES/GCM (or any other method) within an Ionic app to encrypt plain text on the offline device?

So the overall process would be:

  1. Derive a key from a password using scrypt on the server & store it …
  2. Derive the same key using the same password on (every) device.
  3. Use, but don’t store, that key + some crypto function/library to encrypt text on the device.
  4. Store the encrypted text in SQLite db. Decrypt from SQLite using the same key if necessary. The key disappears when the app is closed & is regenerated on next run.
  5. Send the encrypted info to the server, where it’s decrypted using its copy of the same key.

?

So, seems like this requires distributing a shared password to all users so they can generate a key on first run, or else each user has a unique password to generate a unique key, which means all users’ keys need to also be on the server to decrypt the content. If I use an asymmetric public-private key pair instead, they could encrypt on device, but then not decrypt whatever they just stored.

The alternative to encrypting content (or chunks of it) using some to-be-determined crypto function seems to be using SQLCipher to encrypt the entire SQLite database. That takes me back to my original question. Can I use SQLCipher with ‘Storage’ or would I need to replace Storage with the SQLite plugin?

Thanks again ~


#8

I’m not a cryptography expert, but what about:

  1. If offline, derive a key from a password on device
  2. Encrypt data on device with e.g. js-jose
  3. Store encrypted data in ionic-storage
  4. When device is online again, generate key again from password
  5. Decrypt data and send to server with https

?

This way, each user can have their own password and data that is stored on the device is encrypted. You would have to ask for the password whenever a report is saved or read from storage.


#9

WebCrypto. It’s built into the browser itself. MDN docs here, W3C docs here, and a bunch of examples here. One problem you may run into is that the Promises it returns might not be zone-aware. If this does pose a problem for you, one way around it is to merely wrap them inside an explicit Promise.resolve().

Since you (presumably) have SSL to handle transmission, I don’t think you have to worry about key distribution. So the workflow I’m envisioning would work more like this:

  1. On each app run, ask for a password. Different for each user, doesn’t need to be stored or transmitted.
  2. Use scrypt to make an AES key from it.
  3. Import said key into WebCrypto. It will vanish when the app quits.
  4. Use that AES key to encrypt new reports before they go into storage and decrypt old ones as needed.
  5. Send reports to server in plaintext.

Yeah, the primary benefit of that approach would be that it gives you encrypted transmission, but you don’t really need that separately.


#10

Perfect!
That’s exactly what I was looking for, thanks!

Yes, transmission uses https, so I think we’re already good on that front.
Just a ton of stuff to read up on & figure out how to implement.
Thanks for the examples & your patience

Cheers ~