(Y.Text and) end-to-end encryption

I’m currently trying to implement a shared DAG with end-to-end encryption. The structure of the DAG (the “edges”) does not have to be encrypted (it consists of random UUIDs anyway) but the actual value of the “nodes” has to. And, since it’s “end-to-end”, any intermediate servers (e.g. Y-WebSocket) will not be able to decrypt anything.

Encrypting plain and boxed values is trivial, but I would also like to use Y.Text for concurrent editing and still encrypt any contents.

What is the currently recommended way to solve this problem? Will I have to implement my own “encryption-savvy” variant of Y.Text? Should I encrypt the whole Y.Doc? If the latter: where will I have to insert my encryption/decryption code?

[Edit] What currently came into my mind because it was mentioned in another post: encrypting/decrypting doc updates would sound elegant (would the current Y.WebSocket be compatible with such an approach?) - but is there a “hook” where I could add encryption/decryption to a Y.Doc before any update is sent to a provider/after an update was received from a provider?

[Edit] I reread the docs (it’s been quite a while since last time) and came to the following solution:

  • custom implementations of providers are needed (as normal ones are directly bound to a Y.Doc)
  • on the sender side: Y.doc.on(‘update’,…) may be used to get informed about updates. These may then be encrypted as needed and passed to any providers
  • on the receiver side: providers will receive the encrypted update which may then be decrypted and applied to the receiver’s Y.Doc
    This sounds feasible but would require custom providers

Thanks in advance for any hints!

Hey, you might find GitHub - serenity-kit/secsync: Architecture for end-to-end encrypted CRDTs useful as a start. Particularly this file: secsync/packages/secsync-react-yjs/src/useYjsSync.ts at main · serenity-kit/secsync · GitHub

Depending on you app you might also want to consider some form of snapshotting/compaction. In these benchmarks you can see that the missing compression from Yjs, when encrypting each change, results in quite large amounts of data to load: Benchmarks – Nextra

Can you bit more elaborate on your use-case? Then it might be easier to help

1 Like

Thank you very much for your response - I’ll have a look at the references you provided.

Concerning the use case: although it’s a bit more complicated you may just think of my app as an editor for a nested list of notes.