I have a central server to store content. A user can create content and control who can decrypt this content. This needs to be secure using E2EE.

How another user knows whether to fetch this content to try decrypt it is out of the scope of this question.

My initial solution


  1. Content must be encrypted/decrypted with a key pair different from the user creating the content. Otherwise, content the user encrypts with their private key could be decrypted with their public key. Only select users should be able to decrypt this content.
  2. Public keys of those who can decrypt the content should not be publicly known. Meaning - public keys of all users are known, but not specifically those who can decrypt this.
  3. The content must be signed, in order for it to be verified by the end user.
  4. Ideally, this process should be as simple & as fast as possible.

The reason I am not encrypting the content with each other user's public key (PK(A), PK(B), etc.) is because this content may be large - and I do not want the content duplicated when scaling up the users who can decrypt this.

I came up with the following which I believe satisfies all the requirements. However, is there a flaw in my logic or some unnecessary work performed?

Here, we have A making the data to be sent to the server. It can be decrypted by A, B, C, and D. The keys for X are created locally be user A. PK means public key and PS means private key.

Data to be sent to server by A:

Data = encrypt(content, PS(X))

Keys = [
  encrypt(PK(X), PK(A)),
  encrypt(PK(X), PK(B)),
  encrypt(PK(X), PK(C)),
  encrypt(PK(X), PK(D))

Signature = encrypt(hash(content + Keys), PS(A))

This can be decrypted by only A, B, C, and D. They will find PK(X) to decrypt Data to get the content. The Signature is then decrypted with A's public key (PK(A)) and the hashes are compared.

Would this be a secure way to achieve E2EE?

This is my first post here so please let me know if I've done something wrong.


1 Answer 1


However, is there a flaw in my logic or some unnecessary work performed?

Actually, you are performing mostly common practice, except:

  • Why do you make $X$ an asymmetric key? Symmetric keys (e.g. an AES key) would be considerably simpler, and there's no need for the 'someone with only the public key cannot perform the private key operation' property (not to mention that, with most public key systems, you cannot meaningfully 'encrypt' with the private key).

  • One thing you need to be careful (because you care about receiver anonymity) is that not all public key encryption methods give you that. To take a trivial example, if you're using RSA, and E has a 4k RSA key, and none of the key ciphertexts are 4k long, we can be pretty sure that E is not an intended recipient. And, yes, one can come up with less trivial examples.

  • Your example includes 'encrypt(PK(X), PK(A))'; is there a specific reason that $A$ includes himself in the recipient list?

  • You have 'Data = encrypt(content, PS(X))' and 'Signature = encrypt(hash(content + Keys), PS(A))'. Sigh, signatures are not 'encryptions with the private key'; except for RSA, signature methods cannot be usefully described that way (and even for RSA, because the requirements on the padding method differs, even that isn't all that useful...)

  • $\begingroup$ Thank you for the response! I'll go through each point: 1) Very good point, it seems symmetric will do just fine. Also can you elaborate on what I could use to safely encrypt with a private key (or similar)? 2) I can assume the keys will all be the same length, but that is definitely something to keep in mind. I'd think if I hashed the right-half (each user's public key) would get me a constant-length result with no reduction in security (apart from the hash size being the 'weakest link')? 3) No, you can ignore that. $\endgroup$
    – George
    Aug 24, 2022 at 23:10
  • $\begingroup$ 4) I'll have a look more into that. I did think signing and encryption are almost synonymous originally. The encryption library I'm using has a method for signing so I'll definitely use that instead. $\endgroup$
    – George
    Aug 24, 2022 at 23:10
  • $\begingroup$ Back to point 1, since I can use symmetric encryption instead, then I don't need to worry about encrypting with the private key. $\endgroup$
    – George
    Aug 25, 2022 at 10:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.