From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Wed, 06 May 2026 15:26:27 -0700 Received: from mail-ot1-f63.google.com ([209.85.210.63]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wKkhF-0003f2-G1 for bitcoindev@gnusha.org; Wed, 06 May 2026 15:26:27 -0700 Received: by mail-ot1-f63.google.com with SMTP id 46e09a7af769-7dcd603855asf2807595a34.0 for ; Wed, 06 May 2026 15:26:25 -0700 (PDT) ARC-Seal: i=3; a=rsa-sha256; t=1778106379; cv=pass; d=google.com; s=arc-20240605; b=jPgX6k2U9zE3YBO3j1/j1Y/xB7+QuhoETu1qtN3yaHL2TsXpURXkiZvBNfGjvNn25U M+wSv8Cq7QmoRv/Wjr8/GXnGALVSnpo/XERrmg5ZN8Al7PXban0Xr9646AwdyLDFPIRg KPXSVTD2P8G2hkUUb57V+BW3c6ax6bgYieTSpidWgBnKKUUPRA+0nFaTspatNpXu7jGY aD2XWy4oOcBTJsLUJOqGDCXVVFDNPjNIrQbZdfCMySZanwICkVG0ycNJELM5g8jWkZ6v FfARNKF7YhCYYoGzxlAPOUoxHhQ+BGEJXNSda4Y0H7W1Cj88jC//tnPUONYuc5DfjWxK R9yA== ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:sender:dkim-signature :dkim-signature; bh=tiU+B8DMHxUWHvk4QR6Z6huXuOLtyFKQwq0vRIzKPYg=; fh=bZYiJg7aowlfQkQja8EAqaKZJKOZ+i8OwncCp8Lf3OE=; b=MuC6evx09meCrSdQqd4vHZ327JnkOrrkMOh6p8+3viEVG+2iwfF4eP3RmVGAbbOfxP C8QswiFPbCTC3ljs4++7Duq4z8cHhrNaAQe9o2vfirIiubAStoyUbB+hX7opAGlwn7eq I69f8sLXgTwMbjCbQveEx6EhmVB77Ban8BdrQYaTUGzNmI9Mb08fbsD6WI85ceULS08F 2PnjakMWr8unJl1YDqPkVn9/0hAjxgODz97+x3liNNvtBnq2PO+oOad1GuX/rdGWi6n+ FTxP49Qrp3p4vgEzPUWQv0nGx06G262jWh2rJA14R6LC8WEKaAx2nEBkZg5jVcRuUhBD ayWQ==; darn=gnusha.org ARC-Authentication-Results: i=3; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20251104 header.b=ecqzBNFb; arc=pass (i=1); spf=pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b136 as permitted sender) smtp.mailfrom=laolu32@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com; dara=pass header.i=@googlegroups.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1778106379; x=1778711179; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:sender:from:to:cc:subject:date:message-id :reply-to; bh=tiU+B8DMHxUWHvk4QR6Z6huXuOLtyFKQwq0vRIzKPYg=; b=oOUk5W1N4MrGrDxiRfQHLxJ8zWECof/Z2a/hdLEKUqkvg3jb/IB/ay6fjgkfg4KE9U aTX0F02o7rBF3E8VJpphWR/nXxGRqDu9mjHD2besgEuqm6RE4P4ODK6Ek9OKQ//GdywE b0PlcKbHwICleI6f+uO85QSpnXzyVNVnxyfofhOCxBadyYTo8j0fJ0jnlPvHySmXPXqZ YWAMA/JhqNQRxi13ZPYPqs5P6kuMYY3RU1gtIuy/jjEsYTeb7CNXpL6uH8TmG5tknxXm PAPzga1FQchqnxKEnu2XIINWvLaqkVlCmAH9rqPq17dsY+zh7Dx0XPjdbCImxXCYhpEt VecQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778106379; x=1778711179; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:from:to:cc:subject:date:message-id:reply-to; bh=tiU+B8DMHxUWHvk4QR6Z6huXuOLtyFKQwq0vRIzKPYg=; b=DNOsHAi5wRYSosqf9Hll1A0yO54sWKeBZ/LpMcBQkrh+ROgEX3xGJVr7o7sPzuW1ba 47tGuVCbKK8qxC53CCf5UCquKr/7wiJtFoBvK9N2nHZsUrCpGS/5JljJGnKZ6tnoiBZb FdxMuBVsd4rtRICKuTAdAm5q4YL3ugrcxrPGTFfsJOhGhhWdgGNORJTztxF0FPAUV6EU wtQvJyEQwBSKB9fIxysU35ZSz8OdaWH3x0wWJXew2i4IXKOXqVIT4sD2/4OwQG8k0m8h wliHVyfDq27h9J38vnQWEEFiFOz17hARzcNiH19qGHNpGH7DcRNpWs7RMIZxEZ3nrDED UwhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778106379; x=1778711179; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:x-gm-gg:x-beenthere:x-gm-message-state :sender:from:to:cc:subject:date:message-id:reply-to; bh=tiU+B8DMHxUWHvk4QR6Z6huXuOLtyFKQwq0vRIzKPYg=; b=P74UExpzOM/6DlKhUuFi8vJ/yoFOuBMUybYSdllJXvrqKcA9tPDfllvVJqCscMTt21 Y8GEQfJgL0ddeLpXk0pyL7WF20E8mIx+axH4sWP/7A+9a+FPZ1LNoCG1XhzRs18SPd58 cf9igyJFHF1NwQIykiBJd3xmybdjdgew4AMX3CYZDBvJLtxZuJ4whUjIhmjUw4wg1peO Q8VfC2VhMkqEBz01TxTmzY062SkEsRRPX/uzs0ETgNS36n45j1A8GVWB0YVse0eYmnsK G3K2F5oGTzI5JqDI/4NzoWRUoUzBzqqFRk46XAg8t0BeDUEIb9WPSa4wyF6PkVJsounr t3cQ== Sender: bitcoindev@googlegroups.com X-Forwarded-Encrypted: i=3; AFNElJ/TBodryZZ3vKFwz4Ud520Bzakjtls7EZXI9+L/xsN0OEQjgFqF7fHSTfSPIOIKNzMM06eWuWmjpJMN@gnusha.org X-Gm-Message-State: AOJu0YwWj6DKoYhnDdJ1b34kn7szSEcNtm8g2NrZCWlCzqZZFAjotIsx FP7eXDNtqEOqhtfMw2RmMNI384mewIW8tcjTsAsr85H5xD59wZJOCoRK X-Received: by 2002:a05:6820:c8f:b0:67d:e6fa:4488 with SMTP id 006d021491bc7-699ab64e49dmr223126eaf.22.1778106379238; Wed, 06 May 2026 15:26:19 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AUV6zMNwdk5600KSqBo3LR4o3ZGOCOl5ftbZOkY0Alv2QeJb0g==" Received: by 2002:a05:6870:4206:b0:42b:ccd3:8890 with SMTP id 586e51a60fabf-4352567b370ls115621fac.1.-pod-prod-00-us; Wed, 06 May 2026 15:26:14 -0700 (PDT) X-Received: by 2002:a05:6808:2396:b0:467:153a:2d9c with SMTP id 5614622812f47-48061b6e571mr221528b6e.15.1778106374531; Wed, 06 May 2026 15:26:14 -0700 (PDT) Received: by 2002:a05:6808:32ca:b0:47c:339e:add7 with SMTP id 5614622812f47-47c88e7fea0msb6e; Wed, 6 May 2026 15:16:00 -0700 (PDT) X-Received: by 2002:a05:693c:290e:b0:2d9:1c9d:fc22 with SMTP id 5a478bee46e88-2f6e516d94bmr181239eec.21.1778105760058; Wed, 06 May 2026 15:16:00 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1778105760; cv=pass; d=google.com; s=arc-20240605; b=Sy8e+rluMQ+HISowkXN1ett+NDgj5Gcu2Q5Pj29Rste1j3xgzqACj3D1JISeqJhENi jN5WjK66F52iBcEZIb/Lkbfd4446W4oRscbCdu3Mf13I6SyyZZ8IzoqnL0sJp6peZAAf se7HilcXHIaTSsj3TAd9BGJbcEw3uU6tHMu2OrKHQwkFi1o0xPG3LK3p3kuGZCIpY3BZ raCmVvQneNjK3y+BqGl/NtT5BL+sIPsLcyxuq1id8O4X4PM6WeuFw948eLJl+0gzntKw 1dmVRZ2JTYLLJVLBU7tYBYfPbQirQLX4LxNUw9DhvrgEdF6eCHKWa9w2rHKU30eJNV4v B2YQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=3vRi4uo6qa+dRrWXnxLjyCgXbBE/Yno4b+zUDL+qg14=; fh=MhNL3lrwfbsRO5DJHn9ZZ/LeA3+mAuX0vCziGEghh6s=; b=C0qA/hjR7WfQ3YTcrKwccExeW8cvbN3oP+FXNHeDYCMwRZdPTe3o7mexiBMZiv8/fe Q8aP2lffABRJRPCW4WS0pCehIa/QvNguXi/mBAIjY2sXqCqh8WwomH2IBX7qeiWqaV26 AN9y5ELuNycAj6Lon/lokgYbca5eks407HLUmAZB6fPOKDXn99YUk+sDNrUCSj/4KYy1 1iUqlnBEZWbGUeZsIfID1be/WVVLfZOZQ59bbsV+J8ptAgczFpACdtN6RfL5N38Pwm4W oBUWQ4uYYbkK6wDrOapYrjnHMHOXfcxJP/NYzr18YRehJn15yXU5eAmgWiIEqLdcj09z Jgcg==; dara=google.com ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20251104 header.b=ecqzBNFb; arc=pass (i=1); spf=pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b136 as permitted sender) smtp.mailfrom=laolu32@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com; dara=pass header.i=@googlegroups.com Received: from mail-yx1-xb136.google.com (mail-yx1-xb136.google.com. [2607:f8b0:4864:20::b136]) by gmr-mx.google.com with ESMTPS id 5a478bee46e88-2f56edc434fsi152196eec.2.2026.05.06.15.15.59 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 06 May 2026 15:15:59 -0700 (PDT) Received-SPF: pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b136 as permitted sender) client-ip=2607:f8b0:4864:20::b136; Received: by mail-yx1-xb136.google.com with SMTP id 956f58d0204a3-65c7a459105so231510d50.0 for ; Wed, 06 May 2026 15:15:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1778105759; cv=none; d=google.com; s=arc-20240605; b=hhqcVIHSi1qkcIycdV0f/fipmLdu/lcdqOwxDBSjiNb2miqeCeGzlDXT2OVdgCGJAm fDKgRDTthhHRLlMc9b0Vb8UEytZlSefSwnSJP3f3ye9nCH711hRJmGfdeMP67tMayGED OI7fnkJ/UcCcs1Ak2v538+geyPFaj4eZy0VZb/ki9xTwDwKshGW8zjqByLhGNraE7WXk k4vdi5t/bOn0yGhatYY1yHynpreoVrHtR3mIJ/8tO8bG2/QTqir0n5Cu1mG+YBIc0dS1 cg0gydu+TLBLuHwklGI9Tu4CAlnfVLXqe08CCMDjTawkxyPjXBureN9BpKMcM3mJ4HOg HzNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=3vRi4uo6qa+dRrWXnxLjyCgXbBE/Yno4b+zUDL+qg14=; fh=MhNL3lrwfbsRO5DJHn9ZZ/LeA3+mAuX0vCziGEghh6s=; b=jS71GfqXo1+P6mW2SXuejLiVVBDd+ltFw+13kxticcH9O5pe6kd1x0w+1ISCvl82DR ie5dDzAIryZClkiz9B5+V0fA9hoq9+jpOdAhH/ZJUDGGs0mzouSqtiunl1UnIm+EyJE8 ZTqZMgaiOyCR1s2DsLLHgYzg2lSBUTTp2maipFYpGPz1TJZxxBAVr7gt2F1Oo2V7ZDRP fdonPpgGtw+hxm3cZpuATlL9Ttn/C97HbfZz73EWJ8iG+HMgcph0PEP4BNWP/7lf4Jaw 15lbNMOcQ5Q2BQPHESpmmCd1Qw6wZA+JQCCYCFVGtJG7ZyhgoE9u110Ubz91EXmP4AMZ /8Tg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; arc=none X-Gm-Gg: AeBDies1E81+kKPnm+v5JbpT2wuoru90s79mBkq7xkkSC6vZGPBNBZZY5EXAyLqM27b 0iOGOno6GyBVgnabrr9y9LCbZYpp0/uvZno3DsdiMm0zJMcafOmiv+p0A0g4V48Dt7eIYqW6xeM 7ajyFWC5ZwNjyx/2oobLFJAIvmEyjWYFmqqtGFAzxg7H33zDrRowYvNopEMKGq3S1jVWbZEcbrg SW3EQ/zLQj8DjuxiuSD53fSDQHRBUuVihPpvMknfVjYTTzx1xYVVET9hlIyjtnOdUDq942XHkiA /6z2BnMpzD/vCm8BnS+9+vkeCX3ZuPB+sTbo0rRLt+9IH7VqaIxC2l6oPHgPpR0RHQj6audArWe wY/XC6Zg= X-Received: by 2002:a05:690e:12c3:b0:65d:29e1:970b with SMTP id 956f58d0204a3-65d7e779edemr392115d50.14.1778105758748; Wed, 06 May 2026 15:15:58 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Olaoluwa Osuntokun Date: Wed, 6 May 2026 17:15:47 -0500 X-Gm-Features: AVHnY4IXDocCnx21IQlFCPe3TiIEkql4tmOOKFie4n7xkDTyUHlBKoQXYJtZa-8 Message-ID: Subject: Re: [bitcoindev] A Post-Quantum Path for BIP 324 To: Ethan Heilman Cc: Bitcoin Development Mailing List Content-Type: multipart/alternative; boundary="0000000000001f961a06512d825d" X-Original-Sender: laolu32@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20251104 header.b=ecqzBNFb; arc=pass (i=1); spf=pass (google.com: domain of laolu32@gmail.com designates 2607:f8b0:4864:20::b136 as permitted sender) smtp.mailfrom=laolu32@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com; dara=pass header.i=@googlegroups.com Precedence: list Mailing-list: list bitcoindev@googlegroups.com; contact bitcoindev+owners@googlegroups.com List-ID: X-Google-Group-Id: 786775582512 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-Spam-Score: -0.5 (/) --0000000000001f961a06512d825d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Ethan, That's a great question. First, I don't speak for Bitcoin Core by any means (btcd has also implemented BIP 324 FWIW). Based on past observed behavior, they typically prefer to keep dependencies slim. Many years ago there was a concerted push to remove openssl as a dependency from the project. So I would imagine the idea of rolling ou= t full blown TLS 1.3 might encounter some resistance. In terms of cryptography, BIP 324 as defined uses secp256k1. TLS 1.3 as specified doesn't support secp256k1 within the set of supported cipher suites. If ensuring that BIP 324 continues to implement an oblivious KEM is a key requirement, then TLS 1.3 doesn't fit the bill. Regarding a hybrid PQ KEM, there exists an IETF to add a new key agreement suite to TLS 1.3: https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/. Only secp256+384(r1) and x25519 are supported as elliptic curves in this draft. One additional aspect is that today BIP 324 doesn't implement authentication at all, you only get confidentiality. TLS 1.3 would mean introducing certificates in some fashion, thereby coupling concerns from the original PoV of Bip 324= . BIP 324 also includes as section in the BIP detailing the rationale of BIP 324 over a more general purpose protocol (mentions some of the points above): https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki#:~:text=3DWh= y%20not%20use%20a%20general%2Dpurpose%20transport%20encryption%20protocol%3= F . -- Laolu On Tue, May 5, 2026 at 2:18=E2=80=AFPM Ethan Heilman wro= te: > Thanks Laolu for thinking through making PQ BIP 324 and writing this up. > > Reading through what you wrote made me what wonder, why not use this as a= n > opportunity to move to TLS 1.3? > > What's the case against using TLS 1.3 for PQ P2P connection encryption? I= s > there some functionality that TLS 1.3 is lacking that we really want? Is > the case against solely to not have TLS 1.3 as a complex dependency in > bitcoin-core? > > The advantages of TLS 1.3: > > 1. Make Bitcoin P2P connections blend in with all the other TLS > connections. This isn't strong privacy, you can distinguish TLS encrypted > Bitcoin traffic via timing and size, but it reduces accidents where a > firewall sees an unknown protocol and blocks it. > > 2. Use of QUIC for faster relay, oblivious HTTP and QUIC > tunnels-in-tunnels for private relay and similar protocols. > > 3. Lots of eyeballs on TLS 1.3, we don't need to build or maintain it. > > > On Tue, May 5, 2026, 00:41 Olaoluwa Osuntokun wrote: > >> Hi y'all, >> >> In case you weren't already tired of all the recent dev list chatter re >> post >> quantum cryptography, here's another! >> >> When the topic of Bitcoin transitioning to a post quantum world is >> brought up, >> the discussion typically focuses on the consensus layer re swapping out >> vulnerable signature schemes. However, the consensus layer isn't the onl= y >> area >> of Bitcoin that relies in cryptography that would be broken in the face >> of a >> powerful quantum computer! That's right, I'm talking about BIP 324, the >> peer to >> peer encryption BIP for Bitcoin. >> >> Like everything else on the Internet today, BIP 324 uses ECDH to allow t= wo >> connecting peers to derive a shared secret known only to them, which is >> then >> used to encrypt all traffic between them. As ECDH relies on Elliptic Cur= ve >> cryptography, a future quantum computer would be able to eavesdrop on a >> p2p >> handshake transcript, then derive the underlying private keys to the >> ephemeral >> ECDH public key, permitting it to decrypt all traffic. It's actually >> worse than >> that, as today adversaries can collect all encrypted p2p Bitcoin traffic= , >> with >> the hope of being able to decrypt it all at a future date. This is >> commonly >> referred to as the: "harvest, decrypt later" (HNDL) strategy [11]. >> >> Compared to a consensus change, which requires widespread market >> agreement, and >> coordination to achieve, upgrading BIP 324 to be post quantum resistant >> is a >> much lower hanging fruit worthy of pursing immediately. >> >> Last week I starting thinking a bit about this topic, brushing up on the >> latest >> literature/techniques, and stumbled onto a few key design questions. The >> goal >> of this post isn't to propose a new concrete p2p encryption BIP, instead >> I want >> to start discussion on the various design tradeoffs that came up as I wa= s >> researching this p2p encryption transition. >> >> ## PQ BIP 324 Design Questions >> >> 1. Do we want to pursue a hybrid KEM (key encapsulation mechanism), or g= o >> with >> a pure PQ KEM? >> >> 2. Is it still a key requirement that the initial handshake be >> indistinguishable from a random byte string? >> >> 2a. If yes to the above, then should we go with >> classical-then-pq-upgrade, >> or a one shot hybrid oblivious KEM. >> >> >> ## A Brief Intro to KEMs + ML-KEM >> >> First, let's introduce the new primitive we have to work with: ML-KEM >> (Module-Lattice-Based Key-Encapsulation Mechanism) [1][2]. As it says on >> the >> tin, ML-KEM is a lattice based Key-Encapsulation Mechanism. The phrase K= EM >> might sound unfamiliar with those comfortable with ECDH, but ECDH is >> actually a >> KEM itself. >> >> A KEM has 3 algorithms: >> * KeyGen() -> {sk, pk} >> * Generates a public/private secret key pair >> >> * Encaps(pub) -> {secret, capsule} >> * Generates a new secret value, and a "capsule", which only the >> holder of >> pub can use to obtain the secret value. >> >> * Decaps(priv, capsule) -> secret >> * Uses the private key to extract the secret from the capsule >> >> >> If you squint a bit, then you'll see that ECDH is a KEM, and a rather >> elegant >> one at that: >> * KeyGen() -> {k, k*G} >> * Normal EC key generation. >> >> * Encaps(pub) -> {capsule =3D x*G, secret =3D pub*x} >> * The core ECDH routine. The ephemeral public key is actually the >> "capsule". The resulting secret is the ECDH output with the remo= te >> party's KEM public key and the local secret. >> >> * Decaps(priv, capsule) -> secret =3D priv * capsule >> * The receiver completes the key exchange using the ephemeral >> public key >> and their own private key. >> >> ECIES is another flavor of EC based KEM. >> >> One thing worth noting is that AFAICT, so far in the NIST PQC world [4], >> there is >> no known non-interactive key exchange protocol like we enjoy today with >> ECDH. >> IIUC, the reason is that lattice based schemes derived from the LWE [3] >> problem, whose security is predicated on using "noise" to hide a secret >> value. >> For these cryptosystems, usually a type of "hint" is sent to make >> everything >> work out nicely like in ECDH. However, in the stricter non-interactive >> setting >> (no messages sent), this doesn't map cleanly. >> >> As a result, ML-KEM looks more like a hybrid encryption protocol (Alice >> encrypts a shared secret to bob using asymmetric lattice crypto). >> >> ## To Hybrid KEM, Or Not to Hybrid KEM >> >> This brings us to our first design question.... >> >> Should we use a hybrid KEM or a pure post quantum one? >> >> A hybrid KEM would keep the existing ECDH, _also_ do ML-KEM, then secure= ly >> combine (there's some subtlety there, see [6][7]) the resulting in a >> final secret value for encryption. A hybrid KEM is attractive as an >> encryption >> channel derived from such a KEM is secure if _any_ of the combined >> schemes are >> secure. This permits schemes to hedge a bit, as hey, maybe the PQ stuff = is >> actually broken in the future but ECDH isn't. If it's the other way >> around, >> then your encryption scheme is still secure. >> >> ### Pure ML-KEM P2P Encrypted Handshake >> >> If we opt to not use a hybrid scheme, then the Elligator layer can be >> dropped >> all together. Instead, the 1.1 KB (ML-KEM-768) encapsulation keys are >> sent, >> keeping the trailing garbage+terminator in tact. >> >> The initial handshake would look something like: >> * Alice -> Bob: alice_encaps || initiator_garbage >> * Alice derives an encapsulation key, and sends it to Bob. >> >> * Bob -> Alice: ml_kem_capsule || responder_garbage || >> responder_garbage_terminator || first_encrypted_packet >> * Bob uses Alice's encapsulation key to encapsulate a random secret, >> and >> sends it over to Alice. He can also encrypt the first message at th= is >> point. >> >> * Alice -> Bob: initiator_garbage_terminator || first_encrypted_packet >> * Alice de-encapsulates the shared secret, and can now also start to >> encrypt >> messages. >> >> We'd then replace `v2_ecdh` with something like a `v3_mlkem` that derive= s >> the >> final shared secret based on the sent/received transcript up until that >> point: >> * `sha256_tagged("bip324_ml_kem", ml_kem_secret, alice_encaps, >> ml_kem_capsule)` >> >> ### Hybrid ML-KEM P2P Encrypted Handshake >> >> If we want to use a hybrid combiner, then along side the normal ellswift >> keys, >> the ML-KEM-768 encap key is also sent: >> >> * Alice -> Bob: ellswift_alice || alice_encaps || initiator_garbage >> * Bob -> Alice: ellswift_bob || ml_kem_capsule || responder_garbage || >> responder_garbage_terminator || first_encrypted_packet >> * Alice -> Bob: initiator_garbage_terminator || first_encrypted_packet >> >> Then following guidelines of [7], we'd then replace `v2_ecdh` with >> something >> like `v3_hybrid_shared_secret`: >> * `sha256_tagged("bip324_ellswift_xonly_ecdh_mlkem_768", ml_kem_ss, >> ecdh_point_x32, alice_encaps, ml_kem_capsule, ellswift_alice, ellswift_b= ob)` >> >> ## PQ/Hybrid Obfuscated KEMs >> >> At this point, those that are familiar with BIP 324 will recognize that >> both >> the pure PQ and hybrid versions renders the ElligatorSwift usage pretty >> much >> useless. ElligatorSwift encodes a 32-byte public key as a 64-byte value >> which >> is indistinguishable from a uniformly distributed bitstream. In a bubble= , >> this >> means that the initial BIP 324 handshake to a 3rd party observer just >> looks >> like random bytes. However, with the introduction of ML-KEM, the ML-KEM >> encapsulation key is sent in plaintext over the wire. An ML-KEM key has >> identifiable structure, as it's a giant vector of polynomial coefficient= s >> mod >> 3329, which is easily recognizable over the wire. >> >> Luckily, there's an ML-KEM analogue to ElligatorSwift, called Kemeleon >> [8][9][10]! In a similar fashion to ElligatorSwift, it takes an ML-KEM >> public >> key, then encodes it as one giant integer, utilizing rejection sampling. >> Kemeleon applies this mapping both to the encapsulation keys, and also t= he >> capsule ciphertext that encrypts the shared secrets. The ML-KEM keys end >> up >> being a bit smaller, while the ciphertexts map to a larger value. Anothe= r >> tradeoff is that the Kemeleon key generation is ~3x slower than normal >> ML-KEM >> generation. >> >> One thing to note here is that Kemeleon's "looks random" property isn't >> quite >> on the same footing as ElligatorSwift's. ElligatorSwift is statistically >> indistinguishable from random, since every 512-bit string is a valid >> encoding. >> Kemeleon's indistinguishability is computational, resting on a Module-LW= E >> style assumption. So if you naively concatenate an ElligatorSwift key an= d >> a >> Kemeleon key, the pair is only as obfuscated as the weakest visible half= . >> This >> asymmetry is what motivates the OEINC construction discussed below. >> >> This brings us to our second design question.... >> >> Do we still want to ensure that the BIP-324 handshake looks identical to= a >> pseudorandom bytestream from the very first message? >> >> Assuming yes, then AFAICT, we have two classes of options here: >> 1. Retain the existing BIP-324 outer ElligatorSwift handshake, but use >> ML-KEM >> within that initial encrypted transport to upgrade to a PQ shared >> secret. >> >> 2. Use the Outer Encrypts Inner Nested Combiner (OEINC - "OINK") >> combiner >> from [8]. >> >> 3. Attempt to adapt Drivel from [8] into the Bitcoin p2p setting. >> >> ### Classical Encrypted Channel Upgrades to PQ >> >> With the first option, we simply use one KEM right after the other. So >> BIP 324 >> v2 would be mostly unchanged, then we _upgrade_ to BIP 324 v3 within v2. >> >> A sketch of this would be something like: >> * Phase 0: normal BIP 324 handshake >> * Phase 1: negotiation of PQ KEM scheme over the encrypted handshake >> * Can be optional, if we just pick a set PQ KEM scheme. >> * Before this point, no Bitcoin p2p message should be sent, as the >> channel >> isn't PQC protected yet. >> * Phase 2: do normal ML-KEM within the ElligatorSwift derived encrypte= d >> transport >> 1. Alice sends the encapsulation key >> 2. Bob derives a secrets, encrypts it using the encapsulation key >> 3. Both sides then derive a PQ shared secret, ss_PQ >> * Phase 3: both sides use a hybrid combiner like sketched out above to >> derive >> a new set of transport keys >> * Phase 4: both sides rekey, switching over to a new the transport key= s >> >> The upside of this option is that the outer part of BIP 324 remains >> unchanged, >> then with another round trip, we're able to upgrade the encryption keys >> to PQ >> hybrid security. The downside is that the very first messages sent aren'= t >> PQ >> from the start, but a PQ adversary wouldn't be able to decrypt the actua= l >> Bitcoin p2p messages (as we wait to send those until the upgrade). The >> handshake still looks like just random bytes. >> >> ### Outer Encrypts Inner Nested Combiner >> >> For the second option, [8] (with talk video [9] and slides [10]) >> describes an >> OEINC scheme where the outer KEM >> encrypts the inner KEM, wherein the KEM ciphertext of an inner KEM is >> encrypted >> using a shared secret derived from the outer KEM. The two KEM ciphertext= s >> and >> the two derived keys are then used alongside a hybrid combiner to derive= a >> final shared secret. >> >> Unlike the classical-then-pq-upgrade that establishes a classical >> channel, then >> uses that to upgrade to pq channel, OEINC is a special hybrid combiner >> that >> achieves a similar output but in one swoop. It defines a special KEM, >> which can >> then be used as the KEM in the very first handshake I sketched out. >> >> A sketch of this KEM looks something like: >> * Setup: >> * The outer KEM is BIP 324's ElligatorSwift-encoded secp256k1 DHKEM. >> * It serves as the outer KEM because its on-wire encoding is >> statistically indistinguishable from random. >> * The inner KEM is ML-Kemeleon. >> >> * KeyGen(): >> * (kem_secret_outer, kem_pubkey_outer) =3D outKEM.Gen() >> * (kem_secret_inner, kem_pubkey_inner) =3D inKEM.Gen() >> * combined_pubkey =3D (kem_pubkey_outer, kem_pubkey_inner) >> * combined_secret =3D (kem_secret_outer, kem_secret_inner) >> >> * Encaps(combined_pubkey): >> * (shared_secret_outer, capsule_outer) =3D >> outKEM.Encap(kem_pubkey_outer) >> * (encrypt_key_1, encrypt_key_2) =3D KDF(shared_secret_outer) >> * (shared_secret_inner, capsule_inner) =3D inKEM.Encap(kem_pubkey_in= ner) >> * encrypted_capsule_inner =3D encrypt(encrypt_key_1, capsule_inner) >> * combined_capsule =3D capsule_outer || encrypted_capsule_inner >> * combined_shared_secret =3D combine(encrypt_key_2, >> shared_secret_inner, combined_capsule) >> >> * Decaps(combined_secret, combined_capsule): >> * (capsule_outer, encrypted_capsule_inner) =3D combined_capsule >> * shared_secret_outer =3D outKEM.Decaps(kem_secret_outer, capsule_ou= ter) >> * (encrypt_key_1, encrypt_key_2) =3D KDF(shared_secret_outer) >> * capsule_inner =3D decrypt(encrypt_key_1, encrypted_capsule_inner) >> * shared_secret_inner =3D inKEM.Decaps(kem_secret_inner, capsule_inn= er) >> * combined_shared_secret =3D combine(encrypt_key_2, >> shared_secret_inner, combined_capsule) >> >> >> This is done over just sending the two encapsulated secrets plainly as I >> outlined above in order to achieve a stronger security notion. The issue >> with >> this though is that though ciphertext uniformity (the encapsulated >> secrets) is >> achieved, the two public keys sent are randomly looking, but not in a >> uniform >> manner. In practice, this might not really matter much AFAICT (a >> theoretical >> adversary would be able to distinguish the Elligator half from the >> Kemeleon >> half). >> >> ### Drivel: PQ-Obfuscated Authentication >> >> The biggest issue with Drivel as a fit for BIP 324 is that it expects th= e >> initiator to already know a long term static public key for the >> responder. In >> the case of BIP 324, only ephemeral keys are exchanged, so there's no lo= ng >> term public keys known to either side. >> >> To get around this, we could extend BIP 155 (or make a new one likely, >> given >> size limits) to include a signed OKEM key. However then that would >> introduce >> authentication into the combined set, which explicitly wasn't a design >> goal >> of BIP 324. >> >> With that caveat in mind, here's the construction itself. Drivel [8] >> combines >> the OEINC scheme with another layer that out-of-the-box assumes an >> asymmetric >> protocol within a set client and server. The client uses an existing OEI= NC >> KEM public key published by the server to then encrypt a fresh new >> ephemeral >> KEM. >> >> ----- >> >> So there we have it. Before drafting a concrete v3 transport, we need to >> decide if we want a hybrid KEM, or are fine with a pure PQ KEM. Then we >> need to >> decide if we want to attempt to maintain the current quality where the p= 2p >> handshake transcript is indistinguishable from random. If yes, then that >> forces >> another series of decisions re how to construct/compose an oblivious KEM >> from >> available primitives. >> >> At a glance, the route of classical-then-pq-upgrade seems to be the >> simplest. >> BIP 324 stays as is, then we run ML-KEM within that. The ML-KEM keys are >> encrypted, so there's no need to sprinkle in the layer of Kemeleon. >> >> If we want a nice combined protocol, then we should investigate the OEIN= C >> route. It's more data to send as part of the initial handshake, but we >> still >> keep ElligatorSwift and use that as the outer KEM. >> >> If for some reason we're concerned with a future adversary gaining a >> distinguisher for Kemeleon, then maybe we need to bite the bullet and al= so >> roll out a full blown PQ authentication protocol along side everything. >> >> One thing worth flagging for any of the byte-0 designs (where PQ materia= l >> is >> sent in the clear on the very first flight, like the hybrid and OEINC >> sketches >> above): ML-KEM-768 makes the responder do real work before it can decide >> if a >> connection is even legit. Today, the responder only needs the first 64 >> bytes >> of an ElligatorSwift share before it can derive the shared secret. With >> ML-KEM-768, the responder has to read and validate a 1184 byte >> encapsulation >> key before running Encaps, and FIPS 203 mandates input checks on every >> Encaps >> and Decaps. In a permissionless P2P network, that's a meaningful change = in >> inbound DoS surface, and probably calls for stricter handshake byte >> limits, >> tighter timeouts, and possibly some form of stateless cookie/puzzle if >> handshake floods become a real problem. The classical-then-pq-upgrade pa= th >> sidesteps most of this since the PQ material only shows up after the v2 >> channel is up. >> >> With all that said, after the above design decisions are addressed, ther= e >> aren't too many concrete blockers here w.r.t rolling this out. Of course >> the >> development (eg: selecting/creating a library for ML-KEM and maybe >> ML-Kemeleon), and upgrade will take some time. But unlike the consensus >> layer, p2p encryption doesn't require the widespread market agreement >> that an >> actual soft fork does. BIP 324 is a much shorter walk to PQ than the >> consensus >> layer, and serves as a sort of PQ warm up before the bigger soft fork is >> tackled. >> >> >> -- Laolu >> >> [1]: https://en.wikipedia.org/wiki/ML-KEM >> [2]: https://csrc.nist.gov/pubs/fips/203/final >> [3]: https://en.wikipedia.org/wiki/Learning_with_errors >> [4]: This statement ignores Isogeny based crypto, and also SWOOSH [5] as >> it requires 200 KB pubkeys >> [5]: https://eprint.iacr.org/2023/271 >> [6]: https://eprint.iacr.org/2018/024 >> [7]: https://eprint.iacr.org/2020/1364 >> [8]: https://eprint.iacr.org/2024/1086 >> [9]: https://www.youtube.com/watch?v=3DCvFCYUq5rGg >> [10]: >> https://csrc.nist.gov/csrc/media/Presentations/2025/kemeleon/images-medi= a/kemeleon.pdf >> [11]: https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later >> >> -- >> You received this message because you are subscribed to the Google Group= s >> "Bitcoin Development Mailing List" group. >> To unsubscribe from this group and stop receiving emails from it, send a= n >> email to bitcoindev+unsubscribe@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/bitcoindev/CAO3Pvs9U3prZJiDs0Ns7LSA07R= 8hM-GQou_FcTZZz-JUQpUYHw%40mail.gmail.com >> >> . >> > --=20 You received this message because you are subscribed to the Google Groups "= Bitcoin Development Mailing List" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoindev+unsubscribe@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/= CAO3Pvs8i%3DpLP30nRh_iyjSRJXne19wNezmQmo%3DJAk8%2BE4uJPhg%40mail.gmail.com. --0000000000001f961a06512d825d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Ethan,

That's a great question.
First, I don't speak for Bitcoin Core by any means (btcd has also imp= lemented
BIP 324 FWIW). Based on past observed behavior, they typically = prefer to keep
dependencies slim. Many years ago there was a concerted p= ush to remove openssl
as a dependency from the project. So I would imagi= ne the idea of rolling out
full blown TLS 1.3 might encounter some resis= tance.

In terms of cryptography, BIP 324 as defined uses secp256k1. = TLS 1.3 as
specified doesn't support secp256k1 within the set of sup= ported cipher suites.

If ensuring that BIP 324 continues to implemen= t an oblivious KEM is a key
requirement, then TLS 1.3 doesn't fit th= e bill.

Regarding a hybrid PQ KEM, there exists an IETF to add a new= key agreement
suite to TLS 1.3: https://datatracker.ietf.org/doc/draft-ie= tf-tls-ecdhe-mlkem/.
Only secp256+384(r1) and x25519 are supported a= s elliptic curves in this draft.

One additional aspect is that today= BIP 324 doesn't implement authentication at
all, you only get confi= dentiality. TLS 1.3 would mean introducing certificates
in some fashion,= thereby coupling concerns from the original PoV of Bip 324.

BIP 324= also includes as section in the BIP detailing the rationale of BIP 324
= over a more general purpose protocol (mentions some of the points above):https://github.com/bitcoin/bips/blob/master/bip-0324.mediaw= iki#:~:text=3DWhy%20not%20use%20a%20general%2Dpurpose%20transport%20encrypt= ion%20protocol%3F.


-- Laolu



On Tue, May 5, 2026 at 2:18=E2=80=AFPM Ethan Heilman <eth3rs@gmail.com> wrote:
Thanks Laolu for thinking through making PQ BIP 324 and writing this up.
Reading through what you wrote made me what wonder, why not use this = as an opportunity to move to TLS 1.3?

What's the case against us= ing TLS 1.3 for PQ P2P connection encryption? Is there some functionality t= hat TLS 1.3 is lacking that we really want?=C2=A0 Is the case against solely to not have TLS 1.3 as a complex dependency in b= itcoin-core?

The advantages of= TLS 1.3:

1. Make Bitcoi= n P2P connections blend in with all the other TLS connections. This isn'= ;t strong privacy, you can distinguish TLS encrypted Bitcoin traffic via ti= ming and size, but it reduces accidents where a firewall sees an unknown pr= otocol and blocks it.

2.= Use of QUIC for faster relay, oblivious HTTP and QUIC tunnels-in-tunnels f= or private relay and similar protocols.

3. Lots of eyebal= ls on TLS 1.3, we don't need to build or maintain it.


O= n Tue, May 5, 2026, 00:41 Olaoluwa Osuntokun <laolu32@gmail.com> wrote:
Hi y'all= ,

In case you weren't already tired of all the recent dev list = chatter re post
quantum cryptography, here's another!

When th= e topic of Bitcoin transitioning to a post quantum world is brought up,
= the discussion typically focuses on the consensus layer re swapping out
= vulnerable signature schemes. However, the consensus layer isn't the on= ly area
of Bitcoin that relies in cryptography that would be broken in t= he face of a
powerful quantum computer! That's right, I'm talkin= g about BIP 324, the peer to
peer encryption BIP for Bitcoin.

Lik= e everything else on the Internet today, BIP 324 uses ECDH to allow two
= connecting peers to derive a shared secret known only to them, which is the= n
used to encrypt all traffic between them. As ECDH relies on Elliptic C= urve
cryptography, a future quantum computer would be able to eavesdrop = on a p2p
handshake transcript, then derive the underlying private keys t= o the ephemeral
ECDH public key, permitting it to decrypt all traffic. I= t's actually worse than
that, as today adversaries can collect all e= ncrypted p2p Bitcoin traffic, with
the hope of being able to decrypt it = all at a future date. This is commonly
referred to as the: "harvest= , decrypt later" (HNDL) strategy [11].

Compared to a consensus = change, which requires widespread market agreement, and
coordination to = achieve, upgrading BIP 324 to be post quantum resistant is a
much lower = hanging fruit worthy of pursing immediately.

Last week I starting th= inking a bit about this topic, brushing up on the latest
literature/tech= niques, and stumbled onto a few key design questions. The goal
of this p= ost isn't to propose a new concrete p2p encryption BIP, instead I want<= br>to start discussion on the various design tradeoffs that came up as I wa= s
researching this p2p encryption transition.

## PQ BIP 324 Desig= n Questions

1. Do we want to pursue a hybrid KEM (key encapsulation = mechanism), or go with
=C2=A0 =C2=A0a pure PQ KEM?

2. Is it still= a key requirement that the initial handshake be
=C2=A0 =C2=A0indistingu= ishable from a random byte string?

=C2=A0 =C2=A02a. If yes to the ab= ove, then should we go with classical-then-pq-upgrade,
=C2=A0 =C2=A0or a= one shot hybrid oblivious KEM.


## A Brief Intro to KEMs + ML-KE= M

First, let's introduce the new primitive we have to work with:= ML-KEM
(Module-Lattice-Based Key-Encapsulation Mechanism) [1][2]. As it= says on the
tin, ML-KEM is a lattice based Key-Encapsulation Mechanism.= The phrase KEM
might sound unfamiliar with those comfortable with ECDH,= but ECDH is actually a
KEM itself.

A KEM has 3 algorithms:
= =C2=A0 * KeyGen() -> {sk, pk}
=C2=A0 =C2=A0 =C2=A0* Generates a publi= c/private secret key pair

=C2=A0 * Encaps(pub) -> {secret, capsul= e}
=C2=A0 =C2=A0 =C2=A0* Generates a new secret value, and a "capsu= le", which only the holder of
=C2=A0 =C2=A0 =C2=A0 =C2=A0pub can us= e to obtain the secret value.

=C2=A0 * Decaps(priv, capsule) -> s= ecret
=C2=A0 =C2=A0 =C2=A0* Uses the private key to extract the secret f= rom the capsule


If you squint a bit, then you'll see that EC= DH is a KEM, and a rather elegant
one at that:
=C2=A0 * KeyGen() ->= ; {k, k*G}
=C2=A0 =C2=A0 =C2=A0 * Normal EC key generation.

=C2= =A0 * Encaps(pub) -> {capsule =3D x*G, secret =3D pub*x}
=C2=A0 =C2= =A0 =C2=A0 * The core ECDH routine. The ephemeral public key is actually th= e
=C2=A0 =C2=A0 =C2=A0 =C2=A0 "capsule". The resulting secret = is the ECDH output with the remote
=C2=A0 =C2=A0 =C2=A0 =C2=A0 party'= ;s KEM public key and the local secret.

=C2=A0 * Decaps(priv, capsul= e) -> secret =3D priv * capsule
=C2=A0 =C2=A0 =C2=A0 * The receiver c= ompletes the key exchange using the ephemeral public key
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 and their own private key.

ECIES is another flavor of = EC based KEM.

One thing worth noting is that AFAICT, so far in the N= IST PQC world [4], there is
no known non-interactive key exchange protoc= ol like we enjoy today with ECDH.
IIUC, the reason is that lattice based= schemes derived from the LWE [3]
problem, whose security is predicated = on using "noise" to hide a secret value.
For these cryptosyste= ms, usually a type of "hint" is sent to make everything
work o= ut nicely like in ECDH. However, in the stricter non-interactive setting(no messages sent), this doesn't map cleanly.

As a result, ML-K= EM looks more like a hybrid encryption protocol (Alice
encrypts a shared= secret to bob using asymmetric lattice crypto).

## To Hybrid KEM, O= r Not to Hybrid KEM

This brings us to our first design question....<= br>
Should we use a hybrid KEM or a pure post quantum one?

A hyb= rid KEM would keep the existing ECDH, _also_ do ML-KEM, then securely
co= mbine (there's some subtlety there, see [6][7]) the resulting in a
f= inal secret value for encryption. A hybrid KEM is attractive as an encrypti= on
channel derived from such a KEM is secure if _any_ of the combined sc= hemes are
secure. This permits schemes to hedge a bit, as hey, maybe the= PQ stuff is
actually broken in the future but ECDH isn't. If it'= ;s the other way around,
then your encryption scheme is still secure.
### Pure ML-KEM P2P Encrypted Handshake

If we opt to not use a = hybrid scheme, then the Elligator layer can be dropped
all together. Ins= tead, the 1.1 KB (ML-KEM-768) encapsulation keys are sent,
keeping the t= railing garbage+terminator in tact.

The initial handshake would loo= k something like:
=C2=A0* Alice -> Bob: alice_encaps || initiator_ga= rbage
=C2=A0 =C2=A0 * Alice derives an encapsulation key, and sends it t= o Bob.

=C2=A0* Bob -> Alice: ml_kem_capsule || responder_garbage = || responder_garbage_terminator || first_encrypted_packet
=C2=A0 =C2=A0*= Bob uses Alice's encapsulation key to encapsulate a random secret, and=
=C2=A0 =C2=A0 =C2=A0sends it over to Alice. He can also encrypt the fir= st message at this
=C2=A0 =C2=A0 =C2=A0point.

=C2=A0* Alice ->= Bob: initiator_garbage_terminator || first_encrypted_packet
=C2=A0 =C2= =A0* Alice de-encapsulates the shared secret, and can now also start to enc= rypt
=C2=A0 =C2=A0 =C2=A0messages.

We'd then replace `v2_ecdh= ` with something like a `v3_mlkem` that derives the
final shared secret = based on the sent/received transcript up until that point:
=C2=A0 * `sha= 256_tagged("bip324_ml_kem", ml_kem_secret, alice_encaps, ml_kem_c= apsule)`

### Hybrid ML-KEM P2P Encrypted Handshake

If we want= to use a hybrid combiner, then along side the normal ellswift keys,
the= ML-KEM-768 encap key is also sent:

=C2=A0* Alice -> Bob: ellswif= t_alice || alice_encaps || initiator_garbage
=C2=A0* Bob -> Alice: el= lswift_bob || ml_kem_capsule || responder_garbage || responder_garbage_term= inator || first_encrypted_packet
=C2=A0* Alice -> Bob: initiator_garb= age_terminator || first_encrypted_packet

Then following guidelines o= f [7], we'd then replace `v2_ecdh` with something
like `v3_hybrid_sh= ared_secret`:
=C2=A0 * `sha256_tagged("bip324_ellswift_xonly_ecdh_m= lkem_768", ml_kem_ss, ecdh_point_x32, alice_encaps, ml_kem_capsule, el= lswift_alice, ellswift_bob)`

## PQ/Hybrid Obfuscated KEMs

At = this point, those that are familiar with BIP 324 will recognize that boththe pure PQ and hybrid versions renders the ElligatorSwift usage pretty m= uch
useless. ElligatorSwift encodes a 32-byte public key as a 64-byte va= lue which
is indistinguishable from a uniformly distributed bitstream. I= n a bubble, this
means that the initial BIP 324 handshake to a 3rd party= observer just looks
like random bytes. However, with the introduction o= f ML-KEM, the ML-KEM
encapsulation key is sent in plaintext over the wir= e. An ML-KEM key has
identifiable structure, as it's a giant vector = of polynomial coefficients mod
3329, which is easily recognizable over t= he wire.

Luckily, there's an ML-KEM analogue to ElligatorSwift, = called Kemeleon
[8][9][10]! In a similar fashion to ElligatorSwift, it t= akes an ML-KEM public
key, then encodes it as one giant integer, utilizi= ng rejection sampling.
Kemeleon applies this mapping both to the encapsu= lation keys, and also the
capsule ciphertext that encrypts the shared se= crets. The ML-KEM keys end up
being a bit smaller, while the ciphertexts= map to a larger value. Another
tradeoff is that the Kemeleon key genera= tion is ~3x slower than normal ML-KEM
generation.

One thing to no= te here is that Kemeleon's "looks random" property isn't = quite
on the same footing as ElligatorSwift's. ElligatorSwift is sta= tistically
indistinguishable from random, since every 512-bit string is = a valid encoding.
Kemeleon's indistinguishability is computational, = resting on a Module-LWE
style assumption. So if you naively concatenate = an ElligatorSwift key and a
Kemeleon key, the pair is only as obfuscated= as the weakest visible half. This
asymmetry is what motivates the OEINC= construction discussed below.

This brings us to our second design q= uestion....

Do we still want to ensure that the BIP-324 handshake lo= oks identical to a
pseudorandom bytestream from the very first message?<= br>
Assuming yes, then AFAICT, we have two classes of options here:
= =C2=A0 1. Retain the existing BIP-324 outer ElligatorSwift handshake, but u= se ML-KEM
=C2=A0 =C2=A0 =C2=A0within that initial encrypted transport to= upgrade to a PQ shared secret.

=C2=A0 2. Use the Outer Encrypts Inn= er Nested Combiner (OEINC - "OINK") combiner
=C2=A0 =C2=A0 =C2= =A0from [8].

=C2=A0 3. Attempt to adapt Drivel from [8] into the Bit= coin p2p setting.

### Classical Encrypted Channel Upgrades to PQ
=
With the first option, we simply use one KEM right after the other. So = BIP 324
v2 would be mostly unchanged, then we _upgrade_ to BIP 324 v3 wi= thin v2.

A sketch of this would be something like:
=C2=A0 * Phas= e 0: normal BIP 324 handshake
=C2=A0 * Phase 1: negotiation of PQ KEM sc= heme over the encrypted handshake
=C2=A0 =C2=A0 =C2=A0* Can be optional,= if we just pick a set PQ KEM scheme.
=C2=A0 =C2=A0 =C2=A0* Before this = point, no Bitcoin p2p message should be sent, as the channel
=C2=A0 =C2= =A0 =C2=A0 =C2=A0isn't PQC protected yet.
=C2=A0 * Phase 2: do norma= l ML-KEM within the ElligatorSwift derived encrypted
=C2=A0 =C2=A0 trans= port
=C2=A0 =C2=A0 =C2=A01. Alice sends the encapsulation key
=C2=A0 = =C2=A0 =C2=A02. Bob derives a secrets, encrypts it using the encapsulation = key
=C2=A0 =C2=A0 =C2=A03. Both sides then derive a PQ shared secret, ss= _PQ
=C2=A0 * Phase 3: both sides use a hybrid combiner like sketched out= above to derive
=C2=A0 =C2=A0 a new set of transport keys
=C2=A0 * P= hase 4: both sides rekey, switching over to a new the transport keys
The upside of this option is that the outer part of BIP 324 remains unchan= ged,
then with another round trip, we're able to upgrade the encrypt= ion keys to PQ
hybrid security. The downside is that the very first mess= ages sent aren't PQ
from the start, but a PQ adversary wouldn't = be able to decrypt the actual
Bitcoin p2p messages (as we wait to send t= hose until the upgrade). The
handshake still looks like just random byte= s.

### Outer Encrypts Inner Nested Combiner

For the second op= tion, [8] (with talk video [9] and slides [10]) describes an
OEINC schem= e where the outer KEM
encrypts the inner KEM, wherein the KEM ciphertext= of an inner KEM is encrypted
using a shared secret derived from the out= er KEM. The two KEM ciphertexts and
the two derived keys are then used a= longside a hybrid combiner to derive a
final shared secret.

Unli= ke the classical-then-pq-upgrade that establishes a classical channel, then=
uses that to upgrade to pq channel, OEINC is a special hybrid combiner = that
achieves a similar output but in one swoop. It defines a special KE= M, which can
then be used as the KEM in the very first handshake I sketc= hed out.

A sketch of this KEM looks something like:
=C2=A0 * Setu= p:
=C2=A0 =C2=A0 * The outer KEM is BIP 324's ElligatorSwift-encoded= secp256k1 DHKEM.
=C2=A0 =C2=A0 =C2=A0 =C2=A0* It serves as the outer KE= M because its on-wire encoding is
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0stat= istically indistinguishable from random.
=C2=A0 =C2=A0 * The inner KEM i= s ML-Kemeleon.

=C2=A0 * KeyGen():
=C2=A0 =C2=A0 * (kem_secret_out= er, kem_pubkey_outer) =3D outKEM.Gen()
=C2=A0 =C2=A0 * (kem_secret_inner= , kem_pubkey_inner) =3D inKEM.Gen()
=C2=A0 =C2=A0 * combined_pubkey =3D = (kem_pubkey_outer, kem_pubkey_inner)
=C2=A0 =C2=A0 * combined_secret =3D= (kem_secret_outer, kem_secret_inner)

=C2=A0 * Encaps(combined_pubke= y):
=C2=A0 =C2=A0 * (shared_secret_outer, capsule_outer) =3D outKEM.Enca= p(kem_pubkey_outer)
=C2=A0 =C2=A0 * (encrypt_key_1, encrypt_key_2) =3D K= DF(shared_secret_outer)
=C2=A0 =C2=A0 * (shared_secret_inner, capsule_in= ner) =3D inKEM.Encap(kem_pubkey_inner)
=C2=A0 =C2=A0 * encrypted_capsule= _inner =3D encrypt(encrypt_key_1, capsule_inner)
=C2=A0 =C2=A0 * combine= d_capsule =3D capsule_outer || encrypted_capsule_inner
=C2=A0 =C2=A0 * c= ombined_shared_secret =3D combine(encrypt_key_2, shared_secret_inner, combi= ned_capsule)

=C2=A0 * Decaps(combined_secret, combined_capsule):
= =C2=A0 =C2=A0 * (capsule_outer, encrypted_capsule_inner) =3D combined_capsu= le
=C2=A0 =C2=A0 * shared_secret_outer =3D outKEM.Decaps(kem_secret_oute= r, capsule_outer)
=C2=A0 =C2=A0 * (encrypt_key_1, encrypt_key_2) =3D KDF= (shared_secret_outer)
=C2=A0 =C2=A0 * capsule_inner =3D decrypt(encrypt_= key_1, encrypted_capsule_inner)
=C2=A0 =C2=A0 * shared_secret_inner =3D = inKEM.Decaps(kem_secret_inner, capsule_inner)
=C2=A0 =C2=A0 * combined_s= hared_secret =3D combine(encrypt_key_2, shared_secret_inner, combined_capsu= le)


This is done over just sending the two encapsulated secrets = plainly as I
outlined above in order to achieve a stronger security noti= on. The issue with
this though is that though ciphertext uniformity (the= encapsulated secrets) is
achieved, the two public keys sent are randoml= y looking, but not in a uniform
manner. In practice, this might not real= ly matter much AFAICT (a theoretical
adversary would be able to distingu= ish the Elligator half from the Kemeleon
half).

### Drivel: PQ-Ob= fuscated Authentication

The biggest issue with Drivel as a fit for B= IP 324 is that it expects the
initiator to already know a long term stat= ic public key for the responder. In
the case of BIP 324, only ephemeral = keys are exchanged, so there's no long
term public keys known to eit= her side.

To get around this, we could extend BIP 155 (or make a new= one likely, given
size limits) to include a signed OKEM key. However th= en that would introduce
authentication into the combined set, which expl= icitly wasn't a design goal
of BIP 324.

With that caveat in m= ind, here's the construction itself. Drivel [8] combines
the OEINC s= cheme with another layer that out-of-the-box assumes an asymmetric
proto= col within a set client and server. The client uses an existing OEINC
KE= M public key published by the server to then encrypt a fresh new ephemeral<= br>KEM.

-----

So there we have it. Before drafting a concret= e v3 transport, we need to
decide if we want a hybrid KEM, or are fine w= ith a pure PQ KEM. Then we need to
decide if we want to attempt to maint= ain the current quality where the p2p
handshake transcript is indistingu= ishable from random. If yes, then that forces
another series of decision= s re how to construct/compose an oblivious KEM from
available primitives= .

At a glance, the route of classical-then-pq-upgrade seems to be th= e simplest.
BIP 324 stays as is, then we run ML-KEM within that. The ML-= KEM keys are
encrypted, so there's no need to sprinkle in the layer = of Kemeleon.

If we want a nice combined protocol, then we should inv= estigate the OEINC
route. It's more data to send as part of the init= ial handshake, but we still
keep ElligatorSwift and use that as the oute= r KEM.

If for some reason we're concerned with a future adversar= y gaining a
distinguisher for Kemeleon, then maybe we need to bite the b= ullet and also
roll out a full blown PQ authentication protocol along si= de everything.

One thing worth flagging for any of the byte-0 design= s (where PQ material is
sent in the clear on the very first flight, like= the hybrid and OEINC sketches
above): ML-KEM-768 makes the responder do= real work before it can decide if a
connection is even legit. Today, th= e responder only needs the first 64 bytes
of an ElligatorSwift share bef= ore it can derive the shared secret. With
ML-KEM-768, the responder has = to read and validate a 1184 byte encapsulation
key before running Encaps= , and FIPS 203 mandates input checks on every Encaps
and Decaps. In a pe= rmissionless P2P network, that's a meaningful change in
inbound DoS = surface, and probably calls for stricter handshake byte limits,
tighter = timeouts, and possibly some form of stateless cookie/puzzle if
handshake= floods become a real problem. The classical-then-pq-upgrade path
sidest= eps most of this since the PQ material only shows up after the v2
channe= l is up.

With all that said, after the above design decisions are ad= dressed, there
aren't too many concrete blockers here w.r.t rolling = this out. Of course the
development (eg: selecting/creating a library fo= r ML-KEM and maybe
ML-Kemeleon), and upgrade will take some time. But un= like the consensus
layer, p2p encryption doesn't require the widespr= ead market agreement that an
actual soft fork does. BIP 324 is a much sh= orter walk to PQ than the consensus
layer, and serves as a sort of PQ wa= rm up before the bigger soft fork is
tackled.=C2=A0


-- Laolu<= br>
[1]: https://en.wikipedia.org/wiki/ML-KEM
[2]: https://csrc.nist.gov/pubs/fips/203/final
[3]: https://en.wikipedia.org/wiki/Learning_with_errors[4]: This statement ignores Isogeny based crypto, and also SWOOSH [5] as i= t requires 200 KB pubkeys
[5]: https://eprint.iacr.org/2023/271
[6]:
https://eprint.iacr.org/2018/024
[7]: http= s://eprint.iacr.org/2020/1364
[8]: https://eprint.iacr.org/2= 024/1086
[9]: https://www.youtube.com/watch?v=3D= CvFCYUq5rGg
[10]: https://csrc.nist.gov/csrc/media/Presentations/2025/kemeleon/im= ages-media/kemeleon.pdf
[11]: https:/= /en.wikipedia.org/wiki/Harvest_now,_decrypt_later

--
You received this message because you are subscribed to the Google Groups &= quot;Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoindev+unsubscribe@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/CAO3Pvs9U3prZJiDs0= Ns7LSA07R8hM-GQou_FcTZZz-JUQpUYHw%40mail.gmail.com.

--
You received this message because you are subscribed to the Google Groups &= quot;Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoind= ev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.co= m/d/msgid/bitcoindev/CAO3Pvs8i%3DpLP30nRh_iyjSRJXne19wNezmQmo%3DJAk8%2BE4uJ= Phg%40mail.gmail.com.
--0000000000001f961a06512d825d--