<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">I'd have to agree about PKCS 11.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">One more thing about the PQC KEMs - the
      KDF step is built in. As you've mentioned, previously there's been
      a lot of possible combinations with key agreement, with PQC KEMs
      this has changed (of course, you could still use a KDF too, but
      the original reasons for doing so no longer apply).</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Regards,</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">David</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">On 21/8/22 13:52, Michael StJohns
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:6a9103b9-75ab-6bdf-465f-8d966d7d3476@comcast.net">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <div class="moz-cite-prefix">On 8/20/2022 2:08 PM, David Hook
        wrote:<br>
      </div>
      <blockquote type="cite"
        cite="mid:6f95c68c-4cc6-a039-189e-1d4b75b16ca1@cryptoworkshop.com">
        <meta http-equiv="Content-Type" content="text/html;
          charset=UTF-8">
        <div class="moz-cite-prefix">Hi Michael,</div>
        <div class="moz-cite-prefix"><br>
        </div>
        <div class="moz-cite-prefix">I don't know anything about
          bureaucrats, I am an engineer. You may need to consult someone
          else on bureaucrats. <br>
        </div>
        <p>I apologize for my apparent deficiencies in this area, but
          would you mind explaining how Cipher.wrap() is either supposed
          to take a public key and create an encapsulation based on it
          and return a secret key implicitly in one clean move, or why
          it even makes sense to do so. The method was never conceived
          as providing the functionality for what a KEM actually does,
          and when I did the initial PKCS11 implementation at Eracom in
          the late 90's and the team at Sun added the wrap/unwrap
          functions to support it, this is definitely not was intended
          either - it was for explicit key wrapping based on the key
          that was passed to Cipher.init().</p>
      </blockquote>
      <p>First - PKCS11 is a 40 year old API that probably needs to be
        retired.  I spent the better part of 2 years working with the
        PKCS11 Oasis group trying to get them to properly support master
        secrets and KDFs and failed utterly.   You should not use PKCS11
        as an example that the JCE should use as a goal.  <br>
      </p>
      <p><br>
      </p>
      <p>At the base, a java class is a collection of objects.  A Cipher
        object <br>
      </p>
      <p>Let's build a non-parameterized ECIES-KEM which implicitly uses
        AES256 bit keys to key a GCM cipher, and a KDF based on
        SP800-108 counter mode with SHA256 as the underlying hash, and
        with a well known label and context for the KDF since there is a
        new key for every wrap.</p>
      <p>1) Implement CipherSpi - <br>
      </p>
      <p>public class EciesKemCipher extends CipherSpi {</p>
      <p>    private KeyAgreement ka;<br>
            private Cipher gcm;<br>
            private KeyPair kp;<br>
            private KeyPairGenerator kg;</p>
      <p>    EciesKemCipher() {<br>
                ka = KeyAgreement.getInstance("ECDH");<br>
                kpg = KeyPairGenerator.getInstance ("EC");<br>
                gcm = Cipher.getInstance ("AES/GCM/NoPadding");<br>
      </p>
      <p>   }</p>
      <p>   // implement a single example<br>
      </p>
      <p>   @override <br>
            protected void engineInit (int opMode, Key key, SecureRandom
        dontcare) {</p>
      <p>       switch (opMode) {<br>
                 Cipher.MODE_WRAP:<br>
                       initWrap((ECPublicKey) key); <br>
                       break;<br>
                 default:<br>
                   // unimpl<br>
                  }<br>
              }</p>
      <p>    private void initWrap (ECPublicKey k) {</p>
      <p>           ECParameterSpec spec = k.getParams();<br>
                  kpg.initialize(spec);<br>
                  kp = kpg.genKeyPair();<br>
                  ka.init (kp.getPrivate());<br>
                  ka.doPhase (k, true);<br>
                  byte[] sharedSecret = ka.generateSecret();</p>
      <p>          byte[] keyStream = kdf(sharedSecret, 32 + 12); //
        output 44 bytes for Key and IV<br>
                  SecretKeySpec gcmKey = new SecretKeySpec (keyStream,
        0, 32, "AES");<br>
                  IvParameterSpec gcmIv = new IVParameterSpec(keyStream,
        32, 12);<br>
      </p>
      <p>          gcm.init (Cipher.MODE_ENCRYPT, gcmKey, gcmIv);<br>
                  // all ready to go<br>
             } <br>
             <br>
      </p>
      <p>     protected byte[] engineWrap (Key k) {</p>
      <p>           ByteBuffer outData = ByteBuffer.allocate
        (k.getEncoded().length + kp.getPublic().getEncoded().length) +
        16;</p>
      <p>           // Place a copy of the ephemeral public key I
        generated in init here for the use of the receiver.<br>
                   outData.put (kp.getEncoded());<br>
                   // One s<br>
                   outData.put (gcm.doFinal(k.getEncoded());</p>
      <p>            outData.flip();<br>
                    byte[] result = outdata.remaining();</p>
      <p>            outData.get(result);<br>
                    // kp = null; clear cipher if it hasn't already been
        cleared, clear ka if necessary (e.g. un-init)<br>
      </p>
      <p>            return result;<br>
           }<br>
      </p>
      <p>  ... and unwrap and kdf function<br>
        }</p>
      <p><br>
      </p>
      <p>2) Implement a provider and add the above.  <br>
      </p>
      <p><br>
      </p>
      <blockquote type="cite"
        cite="mid:6f95c68c-4cc6-a039-189e-1d4b75b16ca1@cryptoworkshop.com">
        <p>On BC's part, we've already implemented RFC 5990/SP 800-56B
          in Java and the experience has, at best, been awkward. The new
          algorithms have moved awkward to inappropriate. With the new
          algorithms, there's no longer only one case of this, it's not
          an outlier, there should be a general way of supporting KEMs
          in the API that doesn't involve over engineering KeyGenerator
          and Cipher.<br>
        </p>
      </blockquote>
      <p>There's a big difference between the API and your underlying
        implementation.  Everything you want to do can be done using the
        current APIs.  As I said before, Cipher.wrap/unwrap are the
        appropriate APIs for this as they meet the contract requirements
        you need.   Most Ciphers require some extra data -e.g. IVs -
        that have to either be carried or implicitly derived.  In this
        case, what needs to be carried in addition to the encrypted key
        material is at least the ephemeral public key the wrapper
        creates.   I used a very simple encoding scheme above and this
        assumes that both ends know exactly what "ECIES-KEM" means.  
        Obviously, there are 100s of possible combinations of parameters
        and KDFs and key wrap algorithms.   What I would suggest is
        heading over to LAMPS at the IETF and proposing a data encoding
        scheme for carrying the parameters.  Once you have that done,
        then come here and map JCE names against parameter sets to close
        the loop.  It won't require an API change.<br>
      </p>
      <blockquote type="cite"
        cite="mid:6f95c68c-4cc6-a039-189e-1d4b75b16ca1@cryptoworkshop.com">
        <p> </p>
        <p>I work with a team that has had to implement all of them and
          had to make them fit into the JCA. We have done so. Like John,
          I am simply relaying our experience. In about 18 months these
          algorithms are going to become mandatory, what all of us think
          is irrelevant. We, for our part, already have a solution, but
          we both realize it's not "the solution" - we recognize that
          the JVM is uniquely positioned to provide leadership on this
          and provide a universal way of doing it.<br>
        </p>
      </blockquote>
      <p>Then suggest an API and we'll start knocking it around.  I
        personally don't think its necessary at this time and will add
        to API bloat.<br>
      </p>
      <blockquote type="cite"
        cite="mid:6f95c68c-4cc6-a039-189e-1d4b75b16ca1@cryptoworkshop.com">
        <p> </p>
        <p>Of course, if it's felt that these algorithms should be
          ignored, it's not my place to revolt, although I do feel
          obliged to argue. I will simply try and do the best by my
          users, as I have no doubt will John. Both of us have simply
          offered our comments in good faith and to alert the community
          that things have changed and that with these new algorithms
          there is room for a new approach. The ambiguity about how
          these algorithms can be implemented and the excessive need to
          fallback on propritary classes for them does suggest that
          there are some additions to the JCA which would help. I
          appreciate to understand this statement does involve actually
          understanding what these algorithms do and may require some
          additional reading. <br>
        </p>
        <p>As I said, I'm an engineer, my users will be able to use
          these algorithms properly, my team will ensure that, as I have
          no doubt will John's. What John and myself, apparently
          mistakenly, care about is that our users should also be able
          to use these algorithms portably.</p>
        <p>Are you saying portability is no longer a consideration?<br>
        </p>
      </blockquote>
      <p>I have no idea where you got that idea.<br>
      </p>
      <blockquote type="cite"
        cite="mid:6f95c68c-4cc6-a039-189e-1d4b75b16ca1@cryptoworkshop.com">
        <p> </p>
        <p>Regards,</p>
        <p>David<br>
        </p>
        <div class="moz-cite-prefix"><br>
        </div>
        <div class="moz-cite-prefix"><br>
        </div>
        <div class="moz-cite-prefix">On 21/8/22 02:23, Michael StJohns
          wrote:<br>
        </div>
        <blockquote type="cite"
          cite="mid:783df5b7-e30f-08e7-dbc3-e3d95f427c18@comcast.net">
          <meta http-equiv="Content-Type" content="text/html;
            charset=UTF-8">
          <div class="moz-cite-prefix">Hi David/John -</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">I would submit that you're trying
            too hard to make your life simple! :-)</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">Cipher.wrap/unwrap are the
            correct methods.</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">For example:  <br>
          </div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">Cipher  kem = Cipher.getInstance
            ("ECIES/GCM-128-64/KDF-SP800-108-COUNTER-SHA256");</div>
          <div class="moz-cite-prefix">kem.init (Cipher.WRAP_MODE,
            pubkey);</div>
          <div class="moz-cite-prefix">byte[] opaqueEncapsulatedKey =
            kem.wrap (someOtherKey);</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">The "opaqueEncapsulatedKey" would
            contain the data needed by the unwrap function -
            specifically a) the ecies ephemeral public key, b) the fact
            that the derived key is a GCM key of length 128 and that the
            GCM tag is 64 bytes long, c) the KDF, d) (optional) any
            mixins other than defaults required by the KDF - which would
            be passed in a parameter blob during init.  Cipher would NOT
            return the underlying generated secret used to wrap the
            key.  Just the public part of the key pair used to do the
            ECDH operation against the passed in public key.   In the
            RSA case, the wrapped encrypting secret would be an opaque
            data blob and would be part of the data passed to the unwrap
            function.<br>
          </div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">If you want a key generated for
            other purposes, then the right thing is using a KDF and a
            Key agreement function in tandem.   Strangely the KDF
            appears in the javacard API for 3.1, but not in the JCE/JDK
            API.</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">"What's the difference between a
            bureaucrat and an engineer?  A bureaucrat takes small
            solvable pieces and combines them into one insoluble mass."</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">In this case, Java provides a
            number of flexible primitives that can be combined as
            needed.  In this case, the underlying Cipher implementation
            would wrap key agreement and kdf and cipher (GCM)
            instances.  It should return UnsupportedOperationException
            for all operations execept wrap/unwrap and the appropriate
            init methods.</div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">Later, Mike<br>
          </div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix"><br>
          </div>
          <div class="moz-cite-prefix">On 8/19/2022 6:38 PM, David Hook
            wrote:<br>
          </div>
          <blockquote type="cite"
            cite="mid:d511fabf-74dd-ec49-b686-a90eca14861a@cryptoworkshop.com">
            <meta http-equiv="Content-Type" content="text/html;
              charset=UTF-8">
            <div class="moz-cite-prefix">Hi Mike,</div>
            <div class="moz-cite-prefix"><br>
            </div>
            <div class="moz-cite-prefix">KEMs can be used for key
              wrapping - we've actually implemented support for this
              too. But they are not actually key wrapping ciphers.<br>
            </div>
            <div class="moz-cite-prefix"><br>
            </div>
            <div class="moz-cite-prefix">Here's a simple example of
              using Kyber for key wrapping in BC:</div>
            <div class="moz-cite-prefix"><br>
            </div>
            <div class="moz-cite-prefix">
              <pre style="background-color:#ffffff;color:#080808;font-family:'JetBrains Mono',monospace;font-size:11.3pt;"><span style="color:#000000;">SecretKey key </span>= <span style="color:#0033b3;">new </span>SecretKeySpec(<span style="color:#000000;">keyBytes</span>, <span style="color:#067d17;">"AES"</span>);

<span style="color:#000000;">w1</span>.init(<span style="color:#000000;">Cipher</span>.<span style="color:#871094;font-style:italic;">WRAP_MODE</span>, kp.getPublic(), <span style="color:#0033b3;">new </span>KEMParameterSpec(<span style="color:#067d17;">"AES-KWP"</span>));

<span style="color:#0033b3;">byte</span>[] <span style="color:#000000;">data </span>= <span style="color:#000000;">w1</span>.wrap(<span style="color:#000000;">key</span>);

<span style="color:#000000;">Cipher w2 </span>= <span style="color:#000000;">Cipher</span>.<span style="font-style:italic;">getInstance</span>(algorithm, <span style="color:#067d17;">"BCPQC"</span>);

<span style="color:#000000;">w2</span>.init(<span style="color:#000000;">Cipher</span>.<span style="color:#871094;font-style:italic;">UNWRAP_MODE</span>, kp.getPrivate(), <span style="color:#0033b3;">new </span>KEMParameterSpec(<span style="color:#067d17;">"AES-KWP"</span>));

<span style="color:#000000;">Key k </span>= <span style="color:#000000;">w2</span>.unwrap(<span style="color:#000000;">data</span>, <span style="color:#067d17;">"AES"</span>, <span style="color:#000000;">Cipher</span>.<span style="color:#871094;font-style:italic;">SECRET_KEY</span>);

The behavior in this case is in line with what is given in RFC 5990 for the RSA KEM. How it works is by using the key generated
by the KEM to create an AES-KWP key, which is then used to wrap keyBytes. The shortcoming is it means you have to generate the
secret key separately.

This is the problem though - a KEM can actually be used to generate a secret key for other purposes. For example, where 
someone is trying to implement a hybrid KAS scheme. But there is currently no mechanism in the Java APIs for being able to
take advantage of this directly, hence our use of the KeyGenerator class and other people's attempts to make use of the KeyAgreement
class. The Cipher.wrap() returns a byte[] - to be used with a KEM for secret generation it would also have to return the 
generated secret (I would probably also argue that passing a public key to wrap in order to generate an encapsulation of a
generated encrypted secret was not the correct use of the API either, but the fact remains a byte[] is not really going to cut it).

If you have any further questions, please feel free to ask. For what it is worth, I have been developing providers for the JCE/JCA since 
the late 90's and am actually one of the people responsible for the introduction of the existing wrap/unwrap API in the Cipher class.

Thanks,

David
</pre>
            </div>
            <div class="moz-cite-prefix">On 20/8/22 07:53, Mike StJohns
              wrote:<br>
            </div>
            <blockquote type="cite"
              cite="mid:814F78E4-9932-427B-8B65-1AFE5F9D32E2@comcast.net">
              <pre class="moz-quote-pre" wrap="">Hi This implemented as part of Javax.crypto.Cipher.  See the Java doc for the wrap and unwrap methods.  

Mike

Sent from my iPad

</pre>
              <blockquote type="cite">
                <pre class="moz-quote-pre" wrap="">On Aug 19, 2022, at 12:56, John Gray <a class="moz-txt-link-rfc2396E" href="mailto:John.Gray@entrust.com" moz-do-not-send="true"><John.Gray@entrust.com></a> wrote:

 We are starting to make use of the new PQ algorithms adopted by NIST for prototyping and development of standards.   In particular we are working on a composite KEM standard:
See:  <a class="moz-txt-link-freetext" href="https://datatracker.ietf.org/doc/draft-ounsworth-pq-composite-kem/" moz-do-not-send="true">https://datatracker.ietf.org/doc/draft-ounsworth-pq-composite-kem/</a>

However, there is no KEM interface in the JCA (which make sense because these are new algorithms, although RSA-KEM has been out since 2010).

I can add one into our toolkit (and I think David may have already added on into BC),  but I assume at some point there will be an official one added in Java and likely it won't be identical to what we do even if it is very close, which would cause backwards compatibility pain...   Perhaps we could collaborate on extending the JCA to support KEM?      Essentially it requires methods.

ss, ct := encapsulate(PublicKey)
ss := decapsulate(PrivateKey, ct)

-ss is a shared secret (could come back as a Java SecretKey if you wanted as it would usually be used to derive something like an AES afterwards)
-ct is a Cipher Text (a byte array would make sense)
-Public and Private Keys would use the regular public and private key interface.
-An object holding the ss and ct from the encapsulate() method could be returned, with accessor methods to get the ss and ct.   It could be called 'EncapsulatedKEMData' for example.

Likely you would want a new type of KEM crypto object (like you have for Signature, MessageDigest, Cipher, Mac, SecureRandom, KeyAgreement.. etc).   Calling it KEM would seem to make sense.    😊    It could also use similar calling patterns and have a KEM.initKEM(keypair.getPublic()) or KEM.initKEM(keypair.getPrivate()), and then you would just call KEM.encapsulate() or KEM.decapsulate(ct).

Then algorithms could be registered in providers as usual:

   put("KEM.Kyber","com.blah.Kyber")
   put("KEM.compositeKEM","com.entrust.toolkit.crypto.kem.compositeKEM")

Then the above methods (encapsulate and decapsulate) could be defined in that new object type.   Then we would be able to make use of it and not have to worry about incompatibility issues down the road...

Cheers,

John Gray



Any email and files/attachments transmitted with it are confidential and are intended solely for the use of the individual or entity to whom they are addressed. If this message has been sent to you in error, you must not copy, distribute or disclose of the information it contains. Please notify Entrust immediately and delete the message from your system.
</pre>
              </blockquote>
            </blockquote>
            <p><br>
            </p>
          </blockquote>
          <p><br>
          </p>
        </blockquote>
        <p><br>
        </p>
      </blockquote>
      <p><br>
      </p>
    </blockquote>
    <p><br>
    </p>
  </body>
</html>