So, there's that scenario, where I do want to encrypt data which is shared among a group of users. Every user has their own key-pair (RSA-OAEP) where the public key is known to everyone else on the group. There is also a shared secret which every user owns a copy of, encrypted by their public key. When they want to send some data to the other users, they encrypt that data with the shared secret. That is taking place by using AES-GCM, so confidentiality and integrity are provided.

What's left but needed, is authenticity. Data shared with the group by user A could have been sent by anyone who is in posession of the shared secret. There is no guarantee that it really was created by A.

I tried to find any known protocol or schema that matches the simplicity of the described scenario and allows to add some signing, but I was probably searching for the wrong terms.

Anyway, my idea is to sign a hash of the data which is supposed to be shared with the group by user A using their private key, attach that signature to the data and then encrypt it using the shared secret. That way, any participant can verify that it was actually be sent/encrypted by user A as only they are in posession of their private key.

Does that make sense, or am I missing something? And is there a name for that procedure?

  • there's no forward secrecy or post-compromise security in your scheme - everything is static - this means that once the key is discovered "somehow", the entire group history and all future messages will also be exposed - can you please edit your q to clarify whether this matters to your application?
    – brynk
    Jan 24 at 10:09
  • It appears to be that static because I (over)simplified the core building blocks. In reality, more is going on.
    – asp_net
    Jan 24 at 13:07

2 Answers 2


There is nothing materially wrong with this idea, I guess the term for it would be sign-then-encrypt.

A mitigation should be included for replay attacks. Just because someone signed a message at one point, doesn't mean it should be accepted as recently sent forever.

It may be prudent to authenticate what group the message was sent to. If keys are distinct between groups, it shouldn't be an issue. But if an attacker found some way to control the key a group used, it might be considered valid for an unrelated group.

  • Thanks for the feedback! Could you elaborate on where you see the potential for a replay attack? I don't see it right now.
    – asp_net
    Jan 23 at 18:10
  • Jane leads a group of security guards. She sends a message to all security guards requesting their presence in the break room for a meeting. She has on this occasion made sure someone will take their place. An attacker happens to know the contents of this encrypted message makes the guards leave (though they don't know the contents). So they at a later date replay the message to the group, it appears valid and recent and the guards leave their post without planned replacements and the attacker slips through the front gate. Is how I'd write an espionage story around the attack.
    – foreverska
    Jan 23 at 19:17

You sign the message, then encrypt the signed message as well as the sig using AEAD, then presumably send the ciphertext to the others in the group, ie:

nonce = RANDOM_BYTES(nonce_length)
C_msg = AEAD( m|sign(m,user_sign_sk) , nonce , group_secret )
payload = nonce | C_msg

That way, any participant can verify that it was actually be sent/encrypted by user A as only they are in posession of their private key.

Your protocol cannot make such a strong guarantee because nothing binds the sender to the ciphertext. I propose that you sign the ciphertext C_msg instead, for example:

C_msg = AEAD( m , nonce , group_secret )
payload = nonce | C_msg | sign(C_msg... , user_sign_sk)

Aside from the risk of replay as mentioned in @foreverska's answer, there's also no forward secrecy or post-compromise security in your scheme as expressed in your q, meaning that once group_secret becomes exposed, the entire group history and all future messages will also be exposed.

If this doesn't matter then simply consider signing C_msg instead of the plaintext m, and mitigate replay somehow ... otherwise, read on!

(I note that you mention in a recent comment that you had simplified for the purposes of clarity - feel free to edit your q and I might update this answer accordingly.)


If you're worried about members' devices being compromised, and this leading to the exposing of all historical messages, then you must attend to this detail. The general idea here is to change the secret portion/s of any keys in some way that is irreversible. Any copy of old keys must be destroyed on all clients as well, and we assume that honest participants will do this - the security of this solution falls over if any device keeps old keys around.

If you can think of a mechanism that moves forward, but generally won't go backward, one would be the ratchet, hence the name of the "double-ratchet" protocol TPerrin and MMarlinspike'16. The linked spec describes a couple of ways of achieving this depending on your cryptographic primitive ... it's a bit of a misnomer really, because ratchets eventually rotate back around to earlier state, where as key ratcheting will- with overwhelming probability- never return a key to its earlier state, but, as names (and protocols) go, it's pretty damned cool!


Post compromise is about ensuring that the honest participants can move forward securely after one of the group has been evicted. An idea here is to create a random key k for each m and then encrypt k individually for each recipient, aka "pairwise".

Well, this will eliminate forward secrecy if we care about it because every user will by design hold a copy of kx - instead we'd only send a portion of the key material to the others, and assume that they already have the other "ratcheting" portion (ie. the key can't be derived without both portions). Okay, now at least the group can exclude some user user_ex and continue on securely ... ?


... but wait, this assumes the message that user_ex has been evicted reliably makes it to all other members in the group!

As it stands, an adversary that has control of some or all of the group's network could suppress the removal notification for as many other members as possible, except for the one that initiated the exile of user_ex. They would then also intercept the tx of k to user_ex for every new C_msg, and carry on eavesdropping most of the group's exchange... aaargh!

To avoid this trap your protocol might somehow bind every recipient with each new k. This forces group members that derive k to acknowledge all of the expected recipients. Any discrepancy here will alert at least one member... as an added bonus we've introduced non-repudiation of group membership.


The key exchange has now evolved somewhat - we've waved a wand and handled replay, nonce re-use, forward secrecy and post-compromise security. Unfortunately, it still warrants serious criticism for other problems, so I strongly recommend that you don't adopt any of this blindly:

  • unspecified group dis-/enrolment and historical catchup;
  • key revocation/rotation;
  • re-using asymmetric keys for signing of m and encrypting k;
  • and least of all it's lack of efficiency as group-size grows (to the point of being infeasible with a large-enough number of members)

The list would surely go on. Thankfully, there's at least one protocol in the works that has considered all of this and much more! Messaging Layer Security. As of Dec'22 it's not yet standardised, but I predict that it will achieve this status at some point in the future.


  • 1
    Thanks for all the effort you put into writing this up, although it answers many things that are outside of the scope of my question (which is deliberately narrow) :-).
    – asp_net
    Jan 25 at 13:20
  • no worries- securing group exchanges is something i've been thinking about recently in the context of distributed/ parallel processing, so the effort was already being spent .. what parts do you suggest removing? i'd prefer it to be more concise if possible
    – brynk
    Jan 25 at 22:10
  • 1
    I don't think you should remove anything, as all of it can be of value for future readers regardless of my narrower question. I am also digging into this right now as you could probably guess, although in a bit different context. Most of it I already knew, not all of it applies, etc. But as stated, it could be helpful for others. So let's keep it here!
    – asp_net
    Jan 25 at 22:17
  • thanks for the feedback .. just out of interest, what runtime are you implementing in?
    – brynk
    Jan 25 at 22:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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