garbados / comdb

A PouchDB plugin that transparently encrypts and decrypts its data.
61 stars 4 forks source link

Is it possible End to End Encryption? #4

Closed dheimoz closed 3 years ago

dheimoz commented 4 years ago

Hello @garbados , Diana, excellent work you have done here.

I wonder how difficult would be to have End to End Encryption, that way information is safe on both sides. WIth State Management Containers like Redux or Vuex you can have on Ram decrypted information.

I wonder if this makes sense to you.

Once again, thanks for the great job!!

garbados commented 3 years ago

If having decrypted information live only in RAM is sufficient for your needs, you can initialize your PouchDB instance to use the in-memory adapter:

PouchDB.plugin(require('pouchdb-adapter-memory'))
var db = new PouchDB('dbname', {adapter: 'memory'});

Then when you set the password, you can specify your backup target. Then your information is only decrypted in RAM, and the on-disk copy is encrypted.

I'm closing this issue for now but let me know if you have other questions about this.

dheimoz commented 3 years ago

Thanks @garbados however that approach would not work on Offline scenarios. Will try to create an alternative and present a PR.

Once again, thanks for this great plugin.

garbados commented 3 years ago

I am not sure I understand, then. If storing decrypted documents on user disk is not sufficient, but storing decrypted documents in memory isn't either, then I'm not sure what the alternative you're proposing is. Could you explain further?

dheimoz commented 3 years ago

Hi @garbados , yes of course. Your plugin currently encrypts the remote couchdb and the pouchdb is stored in plain text. Meaning if an end user opens his Development tools and goes to storage can find/see the unencrypted information.

What I am proposing is to have both remote Couchdb and local Pouchdb encrypted. Then, with a State Management Library like Redux or Vuex have the information decrypted on the client.

Should you think this is an edge case not worth it, I will understand. Thanks for the follow up Diana.

garbados commented 3 years ago

I think that this is possible with the current architecture. Allow me to explain with a code example:

const db = new PouchDB('local', {adapter: 'memory'})
db.setPassword('goodpassword', { name: 'encrypted-local' })
PouchDB.sync(db._encrypted, 'https://your_couch_url/encrypted-remote')

In this architecture, db is an unencrypted copy of your database which lives in memory. It encrypts its records and stores them in encrypted-local, so that if a user opens up devtools they will only see encrypted data. Then we replicate the encrypted local database with a remote CouchDB installation, so that you can restore from an encrypted remote backup. In fact, the above code will automatically restore from an encrypted backup, because .sync() initiates bidirectional replication.

Does that make sense? I'm re-opening this issue as I now better understand your concerns, and I think they are very relevant to this library.

dheimoz commented 3 years ago

Thanks for reopening @garbados . So far, so good. Unfortunately, in a PWA scenario, the in memory adapter will make the Pouchdb destroyed whenever the user closes the browser. Am I correct?

The idea is to have persistence. Nowadays, Pouchdb works out of the box with Service Workers, and provides offline experience. Combined with the required manifest and workbox configuration strategy you have a full offline cross platform experience.

The expected solution would be that both Pouchdb and Couchdb are encrypted and with a State Management library/ pattern, the data is decrypted and accessed by the client. Without the need to sync with the server every time the user access the page.

As stated, I hope I am not pushing too much the scope of your library. However, this would be missing piece to have a full robust and secure offline experience, provided the Pouchdb is stored and encrypted.

Thank you very much for your time.

garbados commented 3 years ago

Unfortunately, in a PWA scenario, the in memory adapter will make the Pouchdb destroyed whenever the user closes the browser.

Only the in-memory copy. Remember, ComDB keeps an encrypted copy of your data, and in the above configuration that copy remains on disk. So even without server access, a user will be able to reconstruct their data from the encrypted copy on startup using a password or other identifier.

The expected solution would be that both Pouchdb and Couchdb are encrypted and with a State Management library/ pattern, the data is decrypted and accessed by the client. Without the need to sync with the server every time the user access the page.

I feel that this architecture meets these requirements. To lay it out, it keeps three copies of your data:

The user syncs local disk with remote disk to have a remote encrypted backup, so the user can restore their info when switching devices. The local disk populates the in-memory database on startup, so that the only data that remains on disk remains encrypted. The user retains all their information locally, so they do not require network connectivity to use the app normally.

Let me know if anything about this is confusing, or if you feel it still doesn't meet the requirements.

dheimoz commented 3 years ago

Ohhhh @garbados . I am terribly sorry, did not read or understand the fact of the third database and you are absolutely correct. This is the exact architecture needed. You are awesome Diana. Will test and check the behavior.

Thank you very much. Do you mind that I document this architecture in a PR for the Readme?

garbados commented 3 years ago

Sure thing, I'll be happy to review your PR :)

garbados commented 3 years ago

Hi @dheimoz I've added a recipe to the readme about instrumenting E2E encryption: https://github.com/garbados/comdb#recipe-end-to-end-encryption

In short, use the .loadEncrypted() method to bring your decrypted database up to date with your encrypted copies.

Closing this issue for now. Thanks for spurring these additions!

dheimoz commented 3 years ago

Fantastic job Diana. Thank you very much for the effort, your library is greater now!!!!