Open manuerwin opened 10 months ago
if encryption/decryption is done at the client side then I think local storage of the key along with relevant encrypt/decrypt functions would be sufficient to satisfy this feature
Thanks @ChristopherJohnston for replying! Like and agree with the client doing the heavy lifting re: encryption/decryption. Do you have advice on how long the key should be retained in localstorage? or should it be in sessionstorage?
It would be possible to end-to-end encrypt group names, participants names and expense titles, but that would mean having to enter a password the first time accessing the group. The password could be stored in local or session storage, and could even (optionally) be part of the shared URL.
With a different storage implementation, it would also be possible to encrypt all group information. Since there is no shared information between groups, it wouldn’t be for a group data to be stored in an (encrypted) JSON object. This implementation would require dealing with conflicts (maybe with CRDTs?) in case two people update the same group (e.g. add an expense at the same time).
Thanks Sebastien!
I was thinking the simpler version to start as it felt like group names, participants names and expense titles are the data that are “identifiable”.
I’ll have a go at this unless someone beats me to it, may take a few weeks though :p
I had a little play around with the cryptography functions from libp2p, using a local IndexedDB to store the private keys
https://github.com/ChristopherJohnston/libp2p-keychain-encrypt-example
This could be a little bit too much and a lighter solution more appropriate, but I see this working as follows:
On group creation, set a passphrase that would be shared with other members of the group. This could be placed in local storage similarly to the default participant.
The passphrase and groupID are used by the createKey method in libp2p/keychain to create a private key, which is stored in the browser's IndexedDB:
getKeychain(passphrase).createKey(groupId, "rsa", 2048)
getKeychain(passphrase).exportKey(groupId, passphrase)
getKeychain(passcode).importKey(groupId, privateKey, passphrase)
const cms = new CMS(getKeychain(passphrase));
const encryptedValue = cms.encrypt(groupId, uint8ArrayFromString(value, 'ascii'))
const cms = new CMS(getKeychain(passphrase));
const value = cms.decrypt(encryptedValue)
Potential problems:
POC of the above here: https://github.com/scastiel/spliit2/pull/41
Thanks @ChristopherJohnston I think your implementation makes total sense!
If the private key and passphrase are lost, all data is lost
I’m especially worried about this point. I’m afraid it’s hard to let users know that they have to store or remember the passphrase, or the full shared link, somewhere, otherwise no one (even me) will be able to restore access to their group. Many people have trouble with this idea.
An alternative could be to let users decide wether or not they want to encrypt their data, with the advantages and drawback of both options. Again, it would require a bit of clear explanations, and to maintain two distinct logics.
Very much agree with making encryption optional with clear warnings/suggestions (e.g. use a password manager plus regularly backup transactions).
Are there any news regarding this issue?
I’ve not had a chance to look at this yet, hoping to do so next month.
Hey Spliit. Really love the application, it's already come in handy a couple of times. I've read through the thread and wanted to recommend of minibone for this usecase. P.S. For transparency, I'm a co-author, so take my opinion with a pinch of salt.
The library is restricted to only using symmetric encryption (which would be faster than the implementation used in #41) and has a bunch of additional benefits for this particular usecase (like seamlessly handling key rotations). As @scastiel mentioned, the ideal way to derive the password would be to optionally include it in link's fragment or ask users to store it in their password managers.
Happy to chat and/or author a PR if you're happy with the approach.
@david-alm I'm a newb in this space, great to see minibone is built atop the Web Crypto API and agree symmetric key encryption will work well here. Please please go ahead with your PR if you have time :) If not, I'll continue my slow learning journey :p
Just for my understanding, does Vercel Postgres not already encrypt data at rest?
First of all, thanks so much for making this app <3 I would like my shared expense data to be encrypted when stored in the database (either via your hosted implementation or my own).
I’ve had a newb scan of the code and can’t tell if the data stored is encrypted?
if it’s not, how about few fields as possible, perhaps the following?
With an optional passcode/phrase entered on group creation (or later) that encrypts and decrypts the above information for the viewing/interacting user.
The passcode/phrase is shared along with the group url (ideally separately 😅), and entered by a user when using the app (not sure how often though?).
I can certainly have a go at introducing this, however may take me awhile :)