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.)
FORWARD SECRECY
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 SECURITY'S OBVIOUS SOLUTION...
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 ... ?
PROBABLY ISN'T GOOD ENOUGH!
... 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.
SUMMARY
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.
READING