From 38b0c681d175a8da20e22e725cd4ca977caf84b0 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Apr 2026 03:28:12 +0000 Subject: [PATCH] fix(marmot): pass encrypted_group_info as HPKE context for Welcome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 9420 §12.4.3.1 specifies the HPKE context for encrypted_group_secrets must be the encrypted_group_info field of the Welcome: encrypted_group_secrets = EncryptWithLabel(init_key, "Welcome", encrypted_group_info, group_secrets) Both our buildWelcome and processWelcome were passing an empty context, which let Amethyst↔Amethyst round-trips work, but made Welcome messages sent by RFC-compliant implementations (MDK/OpenMLS, used by whitenoise) fail with BAD_DECRYPT inside the HPKE AEAD open. https://claude.ai/code/session_01HfHdd5S5rvxUW2ihEpLGJr --- .../vitorpamplona/quartz/marmot/mls/group/MlsGroup.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/group/MlsGroup.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/group/MlsGroup.kt index a8d99382e..d7e6e6fa3 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/group/MlsGroup.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/group/MlsGroup.kt @@ -1472,12 +1472,13 @@ class MlsGroup private constructor( ) val gsBytes = groupSecrets.toTlsBytes() - // HPKE-encrypt to the member's init_key + // HPKE-encrypt to the member's init_key. Per RFC 9420 + // §12.4.3.1, the HPKE context is the encrypted_group_info. val hpkeCt = MlsCryptoProvider.encryptWithLabel( kp.initKey, "Welcome", - ByteArray(0), + encryptedGroupInfo, gsBytes, ) @@ -1715,12 +1716,13 @@ class MlsGroup private constructor( welcome.secrets.find { it.newMember.contentEquals(myRef) } ?: throw IllegalArgumentException("Welcome does not contain secrets for our KeyPackage") - // HPKE-decrypt group secrets + // HPKE-decrypt group secrets. Per RFC 9420 §12.4.3.1, the HPKE + // context is the encrypted_group_info field of the Welcome. val gsBytes = MlsCryptoProvider.decryptWithLabel( bundle.initPrivateKey, "Welcome", - ByteArray(0), + welcome.encryptedGroupInfo, mySecrets.encryptedGroupSecrets.kemOutput, mySecrets.encryptedGroupSecrets.ciphertext, )