[CFRG] Re: Nailing down non-contributory behaviour in the hybrid-kems drafts
Jack Grigg <ietf@jackgrigg.com> Thu, 16 July 2026 08:14 UTC
Return-Path: <me@jackgrigg.com>
X-Original-To: cfrg@mail2.ietf.org
Delivered-To: cfrg@mail2.ietf.org
Received: from localhost (localhost [127.0.0.1]) by mail2.ietf.org (Postfix) with ESMTP id 1E09C117ABD17 for <cfrg@mail2.ietf.org>; Thu, 16 Jul 2026 01:14:33 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1; t=1784189673; bh=hKZb8n/0k87T9ON7o1zy3Sc/HwKoxD47pDWlAzpKVzc=; h=References:In-Reply-To:Reply-To:From:Date:Subject:To:Cc; b=oRSdTHeQQirwiJR9IIep/TDOQTL+Mu5wSqXJKz6T/5+z3DGG61BYd94WwvxyYiQHI 4VKicMS3NLWZdCk5t+iw2dQQ5bki3Jp+F+Kx/jyWgc+lv9bqX30e0CyZNQX8xbgVXN HkbdSX5LGFsbyTK8X+u4wkUBnGSL8AAh36RsZZvU=
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -1.896
X-Spam-Level:
X-Spam-Status: No, score=-1.896 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from mail2.ietf.org ([166.84.6.31]) by localhost (mail2.ietf.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8HxQGf5S9YZO for <cfrg@mail2.ietf.org>; Thu, 16 Jul 2026 01:14:32 -0700 (PDT)
Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (P-256) server-digest SHA256) (No client certificate requested) by mail2.ietf.org (Postfix) with ESMTPS id 14802117ABD0F for <cfrg@irtf.org>; Thu, 16 Jul 2026 01:14:32 -0700 (PDT)
Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-69c600f76ccso4964682a12.0 for <cfrg@irtf.org>; Thu, 16 Jul 2026 01:14:32 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1784189665; cv=none; d=google.com; s=arc-20260327; b=YjHC+KxkZ/9IRNVTwZgUAEdjna9HD6I41jaO03PzuzCpcOKV0HMXqL67Ykp4B0kDFd xUV3WU2G/F+1rOpZkP7XHMNwroQxyigNFCkMUj1I8p20iXd/SPtPazwS9xxmNzDgbYe8 Olr6dhyWN0MjBoAoLm5S4TdPMCy/ZXZ2Vv3zSjxmsvE1K9pWQ1WyGVeW2Nax+WhWXnIa ge2uG2gCvCXywDAaE4R+J8rLf9E0tcHCx+/+kUx/cluoO4HYnU0A9x+oZy3jVrH3Mg4o V7Ucpf3t0HCHuZ/L38KB1xp/zIfFDPxnGsTQy3usyi+yAXkKMqgypYVHZ/1WpZ7Ie+ap OLGA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:reply-to:in-reply-to:references :mime-version; bh=Q2EtT3VpNwrxcH0yDj0gJ8ezRWzF7yFYUPkmOSeXs2M=; fh=qn4mBQ2L8kmIGVXIRbC1iv/+Qo+Dsiguz1wkqOVTNho=; b=VeN0iH2z9XgC9dBL6sTLVjk3WGr+JP/laQj6/muJ6w7LT8duvcHHQvfnanOlCfj9/o ZCeuy7vXkLWsVAXNNlPiA7J4gOlEwFsfBaoKeiFcTUWywzi6vZA3c8QZLivzZJvkG7px bGzK8GqRQ2bjMVLszTz36JHDNQT31+0weRP1gufyfmfwRoywLjd5UpNOxJFupslfs6ab wqyB7xiqzaOqmjtTv9ru6bY1uRrZOSgOS9tcCWFpIHVRojFzSmF53MErxSuVcYoHxVdU BdvDuMZiZUC/x65SPvPzOvMDc7U8VlQHVELid7IPtz+0Rnm/hJvNhFIb+XliMtE4sKtK 568w==; darn=irtf.org
ARC-Authentication-Results: i=1; mx.google.com; arc=none
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784189665; x=1784794465; h=content-type:cc:to:subject:message-id:date:from:reply-to :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Q2EtT3VpNwrxcH0yDj0gJ8ezRWzF7yFYUPkmOSeXs2M=; b=LYRVc1Wts9lDG3rW6ypiFDPERHovQqSrPWihISQ5G4Z1SWl2hux9e1SErZTtdCU3/4 qs6C0bm/xQq5vgKDJ9uHa0b9BjuV9+OiauZ4f49NXwZR4oCi2uaPGtlAdjuRh1deesrc Ra21AN7oICMjgUQR1dWh5tZdY7/2pwcuWzWzzrouIVMws8kQQ4mkulqEQ/84mWMYyEcj YJ7PanwSrXQA2YTHQAwhgCYx5BuiE3Gvh2Ia6ocZkaveVe/cly16QcDSIcXVzjc4c7em 9yTxsqBVeTZw0FhoeCUF8ZGzZ6Pm9l3HpH4jOO1xT5c/qxBn9WrKNgVyrQoAsAvDRSj9 1Upw==
X-Gm-Message-State: AOJu0YzufbD2XAxb1g0bDYF98tel0mBeHIQo0APWawB+OekyVTFuT0SX SWMX+ehehBVi3qtNCofvKKIjxqTSfEQ7CkyTRGFE3vR5d8mdewCQjEpq1+r70soyfekzPxjx4Tx 3PB+YbVrSbYhTv1iEkhH1O6PmEwrXbUIgTOFe+3pBBQ==
X-Gm-Gg: AfdE7ckyVo/eR/U8JjT88l9PN/Zejto43Q43RLHqs9G3SDD5nly7AJiq/hrZuLzqX4M Mpo+ZM/iEiY06EfGggvWMNi/xvQUdoKTsmCV1Z2BK2bf2nXCuyCafmMpLEg1x8gi96pgp7uQsr3 L/K3hNz1TNoA4RfqdUbTI7cguZAMUpl3lFD43XtZ0SHhZ9YpMSd00hiK0x3GC/mTlwmMqAW4T21 nwYFvbjkS/D9RH4NwoAjH5I5CqaBDMP8f0V/jHJxNmOpFCL1zyjHMm/9kD9fvzO5kBDidN2I6Bu MSKFgbGIs6c8fattXV5V
X-Received: by 2002:a17:906:1389:b0:c12:81bd:c1fc with SMTP id a640c23a62f3a-c161f39d885mr874080666b.31.1784189664826; Thu, 16 Jul 2026 01:14:24 -0700 (PDT)
MIME-Version: 1.0
References: <CAPC=aNXyp1qpsbMiTYjqc=RX8tmWmKCasTS8sKh4Q==UOi+=sQ@mail.gmail.com> <aliEOUowD938uHqL@localhost>
In-Reply-To: <aliEOUowD938uHqL@localhost>
From: Jack Grigg <ietf@jackgrigg.com>
Date: Thu, 16 Jul 2026 09:14:10 +0100
X-Gm-Features: AUfX_myu1k9dRfqqyKIVtoeBzfZoTElDGZSs7s2jzh9tweLLjm1c_89nPDFRcRE
Message-ID: <CAPC=aNWL62Gs4gnE1Da74cC59d7zbnLY9ZVeuvfYenYT=ePpSA@mail.gmail.com>
To: Peter Schwabe <peter@cryptojedi.org>
Content-Type: multipart/alternative; boundary="0000000000002f488f0656b607dd"
Message-ID-Hash: Z54DNRCARXSYCBWQNOXFPRUEAYU2K7JU
X-Message-ID-Hash: Z54DNRCARXSYCBWQNOXFPRUEAYU2K7JU
X-MailFrom: me@jackgrigg.com
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-cfrg.irtf.org-0; header-match-cfrg.irtf.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: IRTF CFRG <cfrg@irtf.org>
X-Mailman-Version: 3.3.9rc6
Precedence: list
Reply-To: ietf@jackgrigg.com
Subject: [CFRG] Re: Nailing down non-contributory behaviour in the hybrid-kems drafts
List-Id: Crypto Forum Research Group <cfrg.irtf.org>
Archived-At: <https://mailarchive.ietf.org/arch/msg/cfrg/OgNdq3QY7C9fax_GK5YjRrEtGTI>
List-Archive: <https://mailarchive.ietf.org/arch/browse/cfrg>
List-Help: <mailto:cfrg-request@irtf.org?subject=help>
List-Owner: <mailto:cfrg-owner@irtf.org>
List-Post: <mailto:cfrg@irtf.org>
List-Subscribe: <mailto:cfrg-join@irtf.org>
List-Unsubscribe: <mailto:cfrg-leave@irtf.org>
My concern is not about whether X-Wing is contributory or not. I do not particularly care about the classical side of the hybrid, and I don't have a strongly-held opinion on whether CFRG should require non-contributory behaviour in X25519 be accepted or rejected. My concern is about the ambiguity in the set of valid ciphertexts. If some entities will accept as valid ciphertexts that others reject, it makes designing some protocols that use those ciphertexts much harder. We had the same problem in Zcash with Ed25519 signatures having wildly inconsistent validity criteria [0], forcing us to define our own verification profile for consensus-critical applications [1]. We could do that because Ed25519 was a leaf primitive used directly, so wrapping existing Ed25519 implementations was (while not trivial) feasible. In the case of X-Wing, the problem is that this ambiguity exists internally to the hybrid. There is no specified way to control the behaviour, and the X25519 shared secret inaccessible for introspection outside of an X-Wing implementation. It might be possible to detect the case externally from the inputs to Decap (or more likely, to HPKE.Open), but that would require parsing values at a layer where they should be opaque, which is brittle and error-prone. It also doesn't help override the internal behaviour of the X-wing implementation (and would probably also require APIs that are not exposed by most X-Wing impls). For my specific use case, the current state of the draft means that anyone wanting to implement PQ age ciphertext decryption has to roll the dice on whether e.g. Apple's X-Wing impl is compatible (an example, I haven't checked it), and if it isn't then they have to manually re-implement X-Wing. That is brittle, error-prone, and a significant barrier to adoption. Cheers, Jack [0] https://hdevalence.ca/blog/2020-10-04-its-25519am/ [1] https://zips.z.cash/zip-0215 On Thu, 16 Jul 2026, 8:11 am Peter Schwabe, <peter@cryptojedi.org> wrote: > Dear Jack, > > If your main concern is about X-Wing being contributory (or not), isn't > that resolved by ML-KEM being contributory? > > All the best, > > Peter > > > Jack Grigg <ietf@jackgrigg.com> wrote: > > Hi all, > > > > While implementing a protocol using X-Wing (specifically post-quantum > > support in age encryption [0] using HPKE), I encountered an > incompatibility > > between two different X-Wing implementations that led me down the > > hybrid-kems rabbit hole, and I uncovered several inconsistencies in the > > drafts that should be resolved. > > > > The core problem stems from Section 6.1 of RFC 7748 [1], which placed a > MAY > > on checking for non-contributory behaviour: > > > > > Both now share K = X25519(a, X25519(b, 9)) = X25519(b, X25519(a, 9)) > as a > > shared secret. Both MAY check, without leaking extra > > > information about the value of K, whether K is the all-zero value and > > abort if so (see below). > > > [...] > > > The check for the all-zero value results from the fact that the X25519 > > function produces that value if it operates on an input corresponding to > a > > point with small order, where the order divides the cofactor of the curve > > (see [Section 7](https://www.rfc-editor.org/info/rfc7748/#section-7)) > > > > Neither the original X-Wing draft [2], nor the ePrint it is based on [3] > > mentioned this, and thus inherently embedded the MAY in its > specification. > > This has led to different X-Wing implementations implementing different > > behaviour, likely based on whatever their existing X25519 implementation > > made most convenient to do. > > > > However, this is seemingly incompatible with the current draft > > specification for X-Wing (aka MLKEM768-X25519) in > > draft-irtf-cfrg-concrete-hybrid-kems-04 [4]. Specifically, Section 4.2 of > > draft-irtf-cfrg-hybrid-kems-12 [5] states: > > > > > A scalar value of zero MUST NOT be used as a private key: it does not > > correspond to a meaningful Diffie-Hellman exchange and, for some curves > > such as P-256, is explicitly forbidden by the relevant standards and > would > > yield a point-at-infinity encoding that departs from the fixed-size model > > used here. RandomScalar MUST NOT return a zero scalar; for the groups of > > interest this occurs only with negligible probability. > > > > A strict reading of the above could be interpreted as allowing > > non-contributory behaviour, because AFAICT there's nothing in the current > > text that actually does the identity check on the nominal group shared > > secret. However, I think these MUST NOTs imply it was the authors' > > intentions to require rejection of non-contributory behaviour. Indeed, if > > you read the specifications of expandDecapsKeyG and prepareEncapsG [6] > with > > those MUST NOTs enforced, then it is impossible to produce a ciphertext > > that would have non-contributory behaviour, and thus an implementation > > could quite justifiably reject those that do. > > > > Further supporting evidence for rejecting non-contributory behaviour in > > IETF KEMs is found in RFC 9180 [7], which makes this a MUST for the > X25519 > > DHKEM (which its update draft [8] preserves). > > > > Now, for an honestly-generated key and ciphertext, the chance of > > encountering this divergence is cryptographically negligible: > > - The Curve25519 scalar within a decapsulation key is a subslice of the > > output of PRG(seed) (via GenerateKeyPair [9] and expandDecapsKeyG). > > - The ephemeral Curve25519 scalar used within encapsulation is the output > > of RandomScalar(random(32)) (via prepareEncapsG), which is constrained by > > the MUST NOT on the output of RandomScalar. > > > > However, for an adversarial ciphertext, there is nothing preventing the > > adversary from using zero as the ephemeral Curve25519 scalar, or a point > of > > small order as the ephemeral public key. Indeed, I encountered this issue > > due to this specific edge case being exercised in age test vectors. So > the > > probability of encountering this divergence is non-negligible, and the > > specs should handle it. > > > > My suggested fix is to alter the definition of ElementToSharedSecret [10] > > to something like: > > > > > ElementToSharedSecret(P) -> ss: Extract a shared secret from an > element > > of the group (e.g., by taking the X coordinate of an elliptic curve > point), > > aborting if a valid shared secret cannot be extracted. > > > > and then for the Curve25519 Nominal Group defined in Section 3.1.2 > > of draft-irtf-cfrg-concrete-hybrid-kems-04 [11], change its > > ElementToSharedSecret specification to: > > > > > ElementToSharedSecret(p) -> ss: Aborts if P is the all-zero value, > > otherwise outputs P. > > > > However, that does then raise the question of whether X-Wing is being > > assumed as purely an implicitly-rejecting KEM (due to how its ML-KEM > > component behaves). I don't believe it was ever valid to assume this, due > > to the MAY in the X25519 component meaning that X25519 implementations > can > > explicitly abort, and thus so might X-Wing. However, if this is a > > widely-held and relied-upon assumption, then it would imply that a > > compatible X-Wing spec would instead need to require that > > expandDecapsKeyG MUST NOT check whether the shared secret is the all-zero > > value, in order to prevent the abort. I myself would prefer that X-Wing > > follow the RFC 9180 precedent and reject non-contributory behaviour. > > > > --- > > > > Regardless of how the above is addressed, at least one other fix is > > necessary. The Curve25519 Nominal Group specifies its RandomScalar as: > > > > > RandomScalar(seed) -> k: Implemented by the identity function, i.e., by > > returning the seed. > > > > This trivially violates the MUST NOT from draft-irtf-cfrg-hybrid-kems-12; > > the all-zero seed produces the forbidden zero scalar. This should be > > similarly updated to: > > > > > RandomScalar(seed) -> k: Aborts if seed is the all-zero value, > otherwise > > returns the seed. > > > > Cheers, > > Jack > > > > [0] https://c2sp.org/age#mlkem768x25519-recipient-stanza > > [1] https://www.rfc-editor.org/info/rfc7748/#section-6.1 > > [2] > https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-10 > > [3] https://eprint.iacr.org/2024/039 > > [4] > > > https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-concrete-hybrid-kems-04#name-mlkem768-x25519 > > [5] > > > https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hybrid-kems-12#section-4.2-4 > > [6] > > > https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hybrid-kems-12#name-using-a-nominal-group > > [7] https://www.rfc-editor.org/info/rfc9180/#section-7.1.4 > > [8] > > > https://datatracker.ietf.org/doc/html/draft-ietf-hpke-hpke-04#name-validation-of-inputs-and-ou > > [9] > > > https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hybrid-kems-12#name-key-generation > > [10] > > > https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hybrid-kems-12#section-4.2-3.3.1 > > [11] > > > https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-concrete-hybrid-kems-04#name-curve25519-nominal-group > > > _______________________________________________ > > CFRG mailing list -- cfrg@irtf.org > > To unsubscribe send an email to cfrg-leave@irtf.org > >
- [CFRG] Nailing down non-contributory behaviour in… Jack Grigg
- [CFRG] Re: Nailing down non-contributory behaviou… Peter Schwabe
- [CFRG] Re: Nailing down non-contributory behaviou… Jack Grigg