Understanding encryption for Real-Time Collaboration
Useful information for understanding how encryption is used with RTCContribute to this page
This documentation is in progress. Please contact us with any suggestions you think should be here.
Caution: The advice on this page does not guarantee a secure connection. If data secrecy is important for your users, please consult a security professional.
Tiny is committed to protecting customer and end-user privacy through end-to-end encryption.
TinyMCE Real-Time Collaboration requires an encryption key:
- To encrypt content before a client sends it to the Tiny Cloud server.
- To decrypt content clients receive from the Tiny Cloud server.
TinyMCE clients use the encryption key but do not transmit it to the Tiny Cloud servers. Tiny will never have the key to decrypt document content.
Encrypted data is indistinguishable from random data without the decryption key. The Real-Time Collaboration (RTC) plugin performs client-side symmetric encryption (using the same key for encryption and decryption) on the editor content. The encryption key is provided to the client by your server, and is never sent to the Tiny Cloud servers; providing end-to-end encryption.
JWT signing does not modify data, and the data can be read by anyone (the data is not encrypted). A JWT signature is transmitted along with the data and is used to validate that the data was not modified after the JWT was created. RTC requires an asymmetric signing algorithm for JWT identity tokens. Asymmetric signing uses a public/private key pair: signatures are created with the private key and verified using the public key. The public key stored on the Tiny Cloud servers can only be used to verify signatures, not create new ones. This allows the Tiny Cloud server to verify that the data contained in the JWT has not been tampered with and is an authentic statement of identity from your server.
Tiny recommends using secure keys for production environments. Real-Time Collaboration (RTC) encryption keys are a string of unicode characters, and can include emoji, such as: “
not a very secret 🔑”.
For test environments, a fixed key can be used. However, in a production environment, encryption keys should be rotated to improve data protection.
Simple, fixed encryption keys provide minimal protection against data disclosure; for details see: RTC encryption details. Simple fixed keys can be a good way to get started with RTC, but if a fixed key is disclosed it can be used to decrypt every document uploaded to the Tiny Cloud server with that key.
Encryption security is a trade off between: the complexity of generating a key, and the risk of compromise should the key be disclosed to an unknown third-party. Methods generate keys include (in descending order of safety):
- Store a global list of keys for your application, and use the document ID along with random data to salt the key on your server to produce a key unique to the document session. Do not send the salt data to any clients; use
keyHintto pass around an identifier that clients can use to request the unique key from the server.
- Use a fixed random key for each document, and generate random salt data to provide a unique key for each session. Pass the salt data to other clients through
keyHint. The salt data will be stored as plain text by the RTC server, but the salt alone cannot be used to decrypt document data.
- Generate and store a fixed random key for each document in your database. Ignore both input and response
The Real-Time Collaboration (RTC) configuration API is designed to support key rotation. Keys cannot be rotated on demand; if this is important to you, please contact Tiny to discuss how we can best provide that functionality.
Document collaboration may be performed in multiple sessions. For example, when a new version of TinyMCE is deployed it may be incompatible with existing sessions. Only one session will be active at a time but older sessions may still be used to bootstrap new sessions. As such, old keys cannot be immediately discarded when a new key is requested.
In order to allow for key rotation a key hint is supplied so the encryption provider may tell the difference between these two cases and act accordingly. If the key hint is
null, then the RTC protocol needs a new key and this is the opportunity for key rotation. If the key hint is not null the protocol is requesting a previously issued key so that it can read the session history.
If the key hint is not included in an encryption provider response for a new key, an empty string will be recorded as the key hint.
Warning: The key hint is stored by the server in plain text. Do not add secret or sensitive information to the key hint.
The key hint can be a key thumbprint, ID, or other non-sensitive identifier that will help select the key, such as a timestamp. It is only recorded when the protocol requests a new key. Returning a key hint from requests for previously issued keys will have no effect.
Note: This section contains the technical details of the encryption used to securely transmit document content. It is provided for information purposes only; an understanding these details is not required to use the RTC plugin.
The Real-Time Collaboration (RTC) plugin does not use the provided encryption key to encrypt content directly. The plugin derives a unique session key from the provided key using industry standard cryptography algorithms. This method of content encryption improves protection against brute force decryption.
Note: Tiny is in the process of changing the RTC encryption method to AES-KW, which does not require an initialization vector or protocol salt. The description below is still correct for the current beta release.
The Real-Time Collaboration (RTC) protocol encryption technique is as follows:
- As described above, each document ID used for collaboration may have multiple sessions. To ensure each session has a unique key, 256 bits of random data are generated as the salt for each session. The salt is generated using the
Crypto.getRandomValues()browser API and a 32 byte
- The salt data and the provided encryption key are combined using a PBKDF2 key derivation function. Derivation is performed by the SubtleCrypto.deriveKey() browser API, using the following parameters:
- The derived key is cached (in memory only) and used with SubtleCrypto.encrypt() and SubtleCrypto.decrypt() as necessary, specifying the AES-GCM algorithm. For each encrypted message, 96 bits of random data are used as the initialization vector, also generated with Crypto.getRandomValues() but this time using a 12 byte
Uint8Array. The initialization vector is transmitted alongside the encrypted message.
- When a real-time collaboration session is established, the provided
keyHintand protocol-generated salt are sent to the server through a HTTPS websocket connection, where they are stored as session metadata. When subsequent clients connect to the session, the server sends these values along with other session information so the client can derive the same unique key.
- The provided key and derived key are never transmitted between clients. Each client will already have the provided key through the rtc_encryption_provider configuration, so only the salt needs to be transmitted for clients to derive the unique key. The salt alone cannot be used to decrypt the document content.
Our choice of encryption parameters results in an expensive derivation process, even on modern hardware, but the derivation is only performed once by each client when connecting to a session. Tiny is committed to the security and privacy of customer data, and Tiny has prioritized increased security over derivation performance. Once derivation is complete, encryption and decryption will be hardware accelerated.
Thanks for the feedback!
Can't find what you're looking for? Let us know.