<html class="apple-mail-supports-explicit-dark-mode"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">On 27 Apr 2026, at 08:14, Werner Koch via Gnupg-users <gnupg-users@gnupg.org> wrote:<blockquote type="cite"><div dir="ltr"><span></span><br><span>The concrete format is based on a</span><br><span>paper and project by the BSI.  </span></div></blockquote><div><br></div><div>It’s more than a “paper and project”, it’s due to be published as an RFC any day now, and is widely implemented (by everyone else).</div><br><blockquote type="cite"><div dir="ltr"><span>The important part from the paper and</span><br><span>prototype project the key-combiner algorithm.  What we changed in</span><br><span>LibrePGP was to replace the way the PGP algorithm ids are assigned to</span><br><span>match how this has always been handled in PGP. </span></div></blockquote><div><br></div><div>That’s not quite true, there are also differences in the fixedinfo and the order of inputs to the KEM combiner (see below) - but I find it fascinating that the algorithm numbering convention is the detail you highlight. Is it really that important?</div><br><blockquote type="cite"><div dir="ltr"><span>The LibrePGP spec is also</span><br><span>easier to read for an implementer as it drops all unneeded theoretical</span><br><span>descriptions.</span><br></div></blockquote><div><br></div><div>The other implementers didn’t seem to mind. :-)</div><br><blockquote type="cite"><div dir="ltr"><span>p.s.</span><br><span></span><br><span>KEM Key Combiner</span><br></div></blockquote><div><br></div><div>For comparison, the equivalent section in the forthcoming RFC can be found at <a href="https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc-15#section-4.2.1">https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-4.2.1</a> :</div><div><br></div><div><div id="kem-key-combiner" style="-webkit-text-size-adjust: auto; box-sizing: border-box;"><section id="section-4.2.1" style="box-sizing: border-box;"><div class="alignLeft art-text artwork" id="section-4.2.1-2" style="box-sizing: border-box; margin-top: var(--line); margin-bottom: var(--line); flex-wrap: nowrap; align-items: end; display: flex;"><pre style="box-sizing: border-box; font-family: var(--bs-font-monospace); font-size: 1em; margin: 0px; overflow: auto clip; padding: 0px; flex: 0 0 content; max-width: 72ch;">KEK = SHA3-256(
          mlkemKeyShare || ecdhKeyShare ||
          ecdhCipherText || ecdhPublicKey ||
          algId || domSep || len(domSep)
      )
return KEK
</pre></div><p id="section-4.2.1-3" style="box-sizing: border-box; margin-top: var(--line); margin-bottom: var(--line); margin-right: 0px; margin-left: 3ch; overflow-wrap: break-word;">The value <code style="box-sizing: border-box; font-family: var(--bs-font-monospace); font-size: 1em; overflow-wrap: break-word; overflow: visible;">domSep</code> is a constant set to the UTF-8 encoding of the string "OpenPGPCompositeKDFv1", that is:</p><div class="alignLeft art-text artwork" id="section-4.2.1-4" style="box-sizing: border-box; margin-top: var(--line); margin-bottom: var(--line); flex-wrap: nowrap; align-items: end; display: flex;"><pre style="box-sizing: border-box; font-family: var(--bs-font-monospace); font-size: 1em; margin: 0px; overflow: auto clip; padding: 0px; flex: 0 0 content; max-width: 72ch;">domSep = 4F 70 65 6E <span dir="ltr" style="box-sizing: border-box; text-decoration-line: underline;">50 47 50 43</span> 6F 6D 70 6F <span dir="ltr" style="box-sizing: border-box; text-decoration-line: underline;">73 69 74 65</span> 4B <span dir="ltr" style="box-sizing: border-box; text-decoration-line: underline;">44 46 76 31</span>
</pre></div><p id="section-4.2.1-5" style="box-sizing: border-box; margin-top: var(--line); margin-bottom: var(--line); margin-right: 0px; margin-left: 3ch; overflow-wrap: break-word;">Here <code style="box-sizing: border-box; font-family: var(--bs-font-monospace); font-size: 1em; overflow-wrap: break-word; overflow: visible;">len(domSep)</code> is the single octet with the value equal to the octet-length of <code style="box-sizing: border-box; font-family: var(--bs-font-monospace); font-size: 1em; overflow-wrap: break-word; overflow: visible;">domSep</code>, that is, decimal 21.</p></section></div><div id="ecc-mlkem-generation" style="-webkit-text-size-adjust: auto; box-sizing: border-box;"></div></div><div><br></div><div>Note however that the LibrePGP text below more closely resembles the first draft of the document:</div><div><br></div><div><a href="https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc-00#section-5.2.2">https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc-00#section-5.2.2</a></div><div><br></div><blockquote type="cite"><div dir="ltr"><span>  For the composite KEM schemes the following procedure MUST be used to</span><br><span>   compute the KEK that wraps a session key.  The construction is a one-</span><br><span>   step key derivation function compliant to [SP800-56C] Section 4,</span><br><span>   based on KMAC256 [SP800-185] and approved by [SP800-227]</span><br><span>   Section 4.6.2.  It is given by the following algorithm:</span><br><span></span><br><span>   multiKeyCombine (eccKeyShare, eccCipherText,</span><br><span>                    mlkemKeyShare, mlkemCipherText,</span><br><span>                    fixedInfo, oBits)</span><br><span></span><br><span>   Input:</span><br><span>   eccKeyShare     - the ECC key share encoded as an octet string</span><br><span>   eccCipherText   - the ECC ciphertext encoded as an octet string</span><br><span>   mlkemKeyShare   - the ML-KEM key share encoded as an octet string</span><br><span>   mlkemCipherText - the ML-KEM ciphertext encoded as an octet string</span><br><span>   fixedInfo       - the fixed information octet string (see below)</span><br><span>   oBits           - the size of the output keying material in bits</span><br><span></span><br><span>   Constants:</span><br><span>   domSeparation       - the UTF-8 encoding of the string</span><br><span>                         "OpenPGPCompositeKeyDerivationFunction"</span><br></div></blockquote><div><br></div><div>Not “LibrePGP”? ;-)</div><br><blockquote type="cite"><div dir="ltr"><span>   counter             - the four-octet big-endian value 0x00000001</span><br><span>   customizationString - the UTF-8 encoding of the string "KDF"</span><br><span></span><br><span>   eccData = eccKeyShare || eccCipherText</span><br><span>   mlkemData = mlkemKeyShare || mlkemCipherText</span><br><span>   encData = counter || eccData || mlkemData || fixedInfo</span><br><span></span><br><span>   result = KMAC256 (domSeparation, encData, oBits, customizationString)</span><br><span></span><br><span>   The fixedinfo is used to provide a binding between the KEK and the</span><br><span>   communication parties.  It is the concatenation of</span><br><span></span><br><span>   *  A one octet algorithm ID describing the symmetric algorithm used</span><br><span>      for the bulk data in the in the SEIPD (packet 18) or the OCBED</span><br><span>      (packet 20).</span><br><span></span><br><span>   *  The 32 octet version 5 fingerprint of the public key.  Note that</span><br><span>      the fingerprint covers the packet format and all other parameters</span><br><span>      of the public key.</span><br><span></span><br><span></span><br><span>-- </span><br><span>The pioneers of a warless world are the youth that</span><br><span>refuse military service.             - A. Einstein</span><br><span>_______________________________________________</span><br><span>Gnupg-users mailing list</span><br><span>Gnupg-users@gnupg.org</span><br><span>https://lists.gnupg.org/mailman/listinfo/gnupg-users</span><br><div><openpgp-digital-signature.asc></div></div></blockquote></body></html>