<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">On rereading, I've realised I neglected
      to comment on the KeyAgreement class.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">It might be useful to see how these
      things would look in practice. For the 3 code fragment below
      vPubKey and vPrivKey should be assumed to be the public and
      private keys of the recipient V. paramSpec is assumed to be
      carrying KDF or other details - it might be absent.<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Using KeyAgreement looks like this:</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    // U side</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    KeyAgreement agreement =
      KeyAgreement.getInstance("Kyber");</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    agreement.init(null, paramSpec); <br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    PublicKey uPub =
      agreement.doPhase(vPubKey, true);</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    byte[] secret =
      agreement.generateSecret();</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    // U sends uPub.getEncoded(), which
      is the encapsulation</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    // V side - V has encoded a byte[]<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    KeyFactory kFact =
      KeyFactory.getInstance("KyberEncapsulation");</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    PublicKey uPub =
      kFact.generatePublic(new X509EncodedKeySpec(encoded));</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    KeyAgreement agreement =
      KeyAgreement.getInstance("Kyber");</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    agreement.init(vPrivKey,
      paramSpec);</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    agreement.doPhase(uPub, true);  //
      return ignored</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">    byte[] secret =
      agreement.generateSecret();</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Up side is there's no new API, down
      side is, to me at least, almost none of the above makes sense, why
      is null passed to U's init? why isn't uPub a real public key? why
      does the encapsulation have to be turned into a PublicKey? why is
      invalid data (probably) being passed to X509EncodedKeySpec? what
      possible relevance is boolean, other than it has to be there?
      Okay, I appreciate these things are in the eye of the beholder,
      but it just looks bad.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Here's what is currently done in BC:</div>
    <div class="moz-cite-prefix">    <br>
    </div>
    <div class="moz-cite-prefix">        // U side</div>
    <div class="moz-cite-prefix">        KeyGenerator keyGen =
      KeyGenerator.getInstance("Kyber");</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">        keyGen.init(new
      KEMGenerateSpec(vPubKey, "AES"), new SecureRandom());<br>
      <br>
              SecretKeyWithEncapsulation secEnc1 =
      (SecretKeyWithEncapsulation)keyGen.generateKey();<br>
    </div>
    <div class="moz-cite-prefix">
      <div class="moz-cite-prefix"><br>
      </div>
      <div class="moz-cite-prefix">        byte[] secret =
        secEnc1.getEncoded();</div>
      <div class="moz-cite-prefix"><br>
      </div>
      <div class="moz-cite-prefix">        // U sends
        secEnc1.getEncapsulation(), which is the encapsulation</div>
      <div class="moz-cite-prefix"><br>
      </div>
      <div class="moz-cite-prefix">        // V side - V has encoded a
        byte[]</div>
      <div class="moz-cite-prefix">        KeyGenerator keyGen =
        KeyGenerator.getInstance("Kyber");</div>
      <div class="moz-cite-prefix"><br>
      </div>
              keyGen.init(new KEMExtractSpec(vPrivKey, encoded, "AES"));<br>
      <br>
              SecretKeyWithEncapsulation secEnc2 =
      (SecretKeyWithEncapsulation)keyGen.generateKey(); <br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">        byte[] secret =
      secEnc2.getEncoded();</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">This feels like it makes more sense,
      but it is stretching the KeyGenerator class a bit (suddenly some
      init() methods don't make sense) and we've also had to introduce
      "vendor specific" classes and it does mean you're always creating
      a SecretKey even if you just want to do a getEncoded() from it. As
      much as I prefer it, it still kind of sucks.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Here, I think, is what John was
      proposing earlier could look like:<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">
      <div class="moz-cite-prefix">        // U side</div>
      <div class="moz-cite-prefix">        KEM kem =
        KEM.getInstance("Kyber");</div>
      <div class="moz-cite-prefix"><br>
      </div>
      <div class="moz-cite-prefix">        kem.initGenerate(vPubKey,
        paramSpec, new SecureRandom());<br>
        <br>
                byte[] encapsulation = kem.generateEncapsulation();</div>
      <div class="moz-cite-prefix"><br>
      </div>
      <div class="moz-cite-prefix">        byte[] secret =
        kem.generateSecret();<br>
      </div>
      <div class="moz-cite-prefix">
        <div class="moz-cite-prefix"><br>
        </div>
        <div class="moz-cite-prefix">        // U sends encapsulation to
          V<br>
        </div>
        <div class="moz-cite-prefix"><br>
        </div>
        <div class="moz-cite-prefix">        // V side - V has
          encapsulation a byte[]</div>
        <div class="moz-cite-prefix">        KEM kem =
          KEM.getInstance("Kyber");</div>
        <div class="moz-cite-prefix"><br>
        </div>
        <div class="moz-cite-prefix">        kem.initExtract(vPrivKey,
          paramSpec);<br>
          <br>
        </div>
        <div class="moz-cite-prefix">        byte[] secret =
          kem.extractSecret(encapsulation);</div>
      </div>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">As I said, "could look like", I'm not
      saying "should", but it's really much cleaner, simpler, and less
      confusing than the first two, and I really think the above
      demonstrates that these new algorithms are really not properly
      covered in the existing API.</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<br>
    </div>
    <div class="moz-cite-prefix">On 21/8/22 04:08, 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>
      <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>
      <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>
      <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>
      <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>
  </body>
</html>