<html class="apple-mail-supports-explicit-dark-mode"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><span style="-webkit-text-size-adjust: auto; background-color: rgb(44, 44, 46);">On 27 Apr 2026, at 08:14, Werner Koch via Gnupg-users <</span><span dir="ltr" style="-webkit-text-size-adjust: auto;">gnupg-users@gnupg.org</span><span style="-webkit-text-size-adjust: auto; background-color: rgb(44, 44, 46);">> wrote:</span><blockquote type="cite" style="color: rgb(255, 255, 255); -webkit-text-size-adjust: auto;"><div dir="ltr"><br>The concrete format is based on a<br>paper and project by the BSI.  </div></blockquote><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;">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 style="-webkit-text-size-adjust: auto;"><blockquote type="cite" style="color: rgb(255, 255, 255); -webkit-text-size-adjust: auto;"><div dir="ltr">The important part from the paper and<br>prototype project the key-combiner algorithm.  What we changed in<br>LibrePGP was to replace the way the PGP algorithm ids are assigned to<br>match how this has always been handled in PGP. </div></blockquote><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;">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 style="-webkit-text-size-adjust: auto;"><blockquote type="cite" style="color: rgb(255, 255, 255); -webkit-text-size-adjust: auto;"><div dir="ltr">The LibrePGP spec is also<br>easier to read for an implementer as it drops all unneeded theoretical<br>descriptions.<br></div></blockquote><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;">The other implementers didn’t seem to mind. :-)</div><br style="-webkit-text-size-adjust: auto;"><blockquote type="cite" style="color: rgb(255, 255, 255); -webkit-text-size-adjust: auto;"><div dir="ltr">p.s.<br><br>KEM Key Combiner<br></div></blockquote><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;">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 style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;"><div id="kem-key-combiner" style="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><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;"><br></pre><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;"><span dir="ltr">50 47 50 43</span></span> 6F 6D 70 6F <span dir="ltr" style="box-sizing: border-box; text-decoration-line: underline;"><span dir="ltr">73 69 74 65</span></span> 4B <span dir="ltr" style="box-sizing: border-box; text-decoration-line: underline;"><span dir="ltr">44 46 76 31</span></span></pre><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;"><span dir="ltr" style="box-sizing: border-box; text-decoration-line: underline;"><span dir="ltr"><br></span></span></pre><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;">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="box-sizing: border-box;"></div></div><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;">Note however that the LibrePGP text below more closely resembles the first draft of the document:</div><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;"><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 style="-webkit-text-size-adjust: auto;"><br></div><blockquote type="cite" style="color: rgb(255, 255, 255); -webkit-text-size-adjust: auto;"><div dir="ltr">  For the composite KEM schemes the following procedure MUST be used to<br>  compute the KEK that wraps a session key.  The construction is a one-<br>  step key derivation function compliant to [SP800-56C] Section 4,<br>  based on KMAC256 [SP800-185] and approved by [SP800-227]<br>  Section 4.6.2.  It is given by the following algorithm:<br><br>  multiKeyCombine (eccKeyShare, eccCipherText,<br>                   mlkemKeyShare, mlkemCipherText,<br>                   fixedInfo, oBits)<br><br>  Input:<br>  eccKeyShare     - the ECC key share encoded as an octet string<br>  eccCipherText   - the ECC ciphertext encoded as an octet string<br>  mlkemKeyShare   - the ML-KEM key share encoded as an octet string<br>  mlkemCipherText - the ML-KEM ciphertext encoded as an octet string<br>  fixedInfo       - the fixed information octet string (see below)<br>  oBits           - the size of the output keying material in bits<br><br>  Constants:<br>  domSeparation       - the UTF-8 encoding of the string<br>                        "OpenPGPCompositeKeyDerivationFunction"<br></div></blockquote><div style="-webkit-text-size-adjust: auto;"><br></div><div style="-webkit-text-size-adjust: auto;">Not “LibrePGP”? ;-)</div><br style="-webkit-text-size-adjust: auto;"><blockquote type="cite" style="color: rgb(255, 255, 255); -webkit-text-size-adjust: auto;"><div dir="ltr">  counter             - the four-octet big-endian value 0x00000001<br>  customizationString - the UTF-8 encoding of the string "KDF"<br><br>  eccData = eccKeyShare || eccCipherText<br>  mlkemData = mlkemKeyShare || mlkemCipherText<br>  encData = counter || eccData || mlkemData || fixedInfo<br><br>  result = KMAC256 (domSeparation, encData, oBits, customizationString)<br><br>  The fixedinfo is used to provide a binding between the KEK and the<br>  communication parties.  It is the concatenation of<br><br>  *  A one octet algorithm ID describing the symmetric algorithm used<br>     for the bulk data in the in the SEIPD (packet 18) or the OCBED<br>     (packet 20).<br><br>  *  The 32 octet version 5 fingerprint of the public key.  Note that<br>     the fingerprint covers the packet format and all other parameters<br>     of the public key.<br><br><br>-- <br>The pioneers of a warless world are the youth that<br>refuse military service.             - A. Einstein<br>_______________________________________________<br>Gnupg-users mailing list<br><span dir="ltr">Gnupg-users@gnupg.org</span><br><span dir="ltr">https://lists.gnupg.org/mailman/listinfo/gnupg-users</span></div></blockquote></body></html>