<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>