Thanks David for your Support.

I have been developing cryptographic algorithms in our Entrust Java toolkit 
since the early 2000’s, so between us we have a lot of years of experience 
using the JCA.   😊

Mike,  a KEM is not a Cipher.   I think of it as a kind of middle ground 
between a Key Agreement and a Cipher.    That is why it can be forced to fit in 
either model, but it doesn’t fit well with either of them.   Not having a clean 
KEM API will lead to lots of confusion, likely implementation bugs and 
inconsistent usage.  The Cipher.wrap () is not the same as a KEM.encapsulate(). 
  As David mentions, wrap() returns a byte[], but a KEM actually returns a 
shared secret AND a Ciphertext.    The PQ algorithm “Kyber” selected by NIST is 
a KEM and it will return a shared-secret that it has generated internally.    
Returning only a byte[] is not good enough even if you did a naïve 
concatenation as you would then have to know the shared-secret length and the 
cipherText length and you would have to have an agreement with the producing 
party on which order they came back.  For example, if David implemented SS || 
Ciphertext in BC and I implemented CipherText || SS in our Entrust toolkit, we 
would fail to interoperate.   At minimum we would need to agree on the order, 
and we would need a function tied to a KEM Cipher to properly separate the 
values.  This just seems like a mess that could be easily solved by adding a 
clean KEM interface in the JCA.   Otherwise everyone is going to try to fit it 
into the JCA in their own inconsistent way, no one will agree, and we will have 
lots of interoperability problems down the road.  David example below shows it 
*can* fit, but it is not ideal because you have limited what the key can be 
used for, and the calling convention is not straight forward like Cipher or 
Signature are today.
KEM allows the establishment of a common shared-secret between two parties, but 
does not combine the public key and private key of different parties together 
to obtain the shared secret (like in a Key Agreement).   Instead an 
encapsulation(PublicKey) takes a public key and outputs a CipherText AND Shared 
Secret.    The Shared Secret can be used to derive a SecretKey (like AES) to 
perform encryption operations or the key could be used to generate a key for 
other purposes.   On the receiving side, the CipherText needs to be combined 
with the receivers private key (in this regard it is like a Cipher), but it 
outputs a shared-secret which as mentioned can have many different purposes.   
KEM has a lot of interesting properties in that the Ciphertexts length is fixed 
and based on the algorithm.   For example, Kyber's CipherText size is 768 bytes 
at lowest security and 1568 bytes at highest security.   For an HSM use-case, 
it would be very feasible to use KEM as a key transport mechanism to set up the 
symmetric keys for protection of keys to and from the HSM, or for use-cases 
which require centralized/HSM generation of symmetric keys (for example a FIPS 
engine) which can’t be done efficiently by a Cipher.   KEM could also be used 
as a proof-of-possession or in challenge response scenarios.   There are many 
other uses we could enumerate.   KEM seems to be the way forward in terms of 
the NIST standardization process, so it makes sense for us to implement a 
proper KEM interface in Java now.
Cheers,

John Gray


From: David Hook <d...@cryptoworkshop.com>
Sent: Friday, August 19, 2022 6:38 PM
To: Mike StJohns <mstjo...@comcast.net>; John Gray <john.g...@entrust.com>
Cc: security-dev@openjdk.org
Subject: [EXTERNAL] Re: Is there a KEM (Key Encapsulation Mechanism) 
architecture being proposed for the JCA?

WARNING: This email originated outside of Entrust.
DO NOT CLICK links or attachments unless you trust the sender and know the 
content is safe.
________________________________
Hi Mike,

KEMs can be used for key wrapping - we've actually implemented support for this 
too. But they are not actually key wrapping ciphers.

Here's a simple example of using Kyber for key wrapping in BC:


SecretKey key = new SecretKeySpec(keyBytes, "AES");



w1.init(Cipher.WRAP_MODE, kp.getPublic(), new KEMParameterSpec("AES-KWP"));



byte[] data = w1.wrap(key);



Cipher w2 = Cipher.getInstance(algorithm, "BCPQC");



w2.init(Cipher.UNWRAP_MODE, kp.getPrivate(), new KEMParameterSpec("AES-KWP"));



Key k = w2.unwrap(data, "AES", Cipher.SECRET_KEY);



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
On 20/8/22 07:53, Mike StJohns wrote:

Hi This implemented as part of Javax.crypto.Cipher.  See the Java doc for the 
wrap and unwrap methods.



Mike



Sent from my iPad



On Aug 19, 2022, at 12:56, John Gray 
<john.g...@entrust.com><mailto:john.g...@entrust.com> 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:  
https://datatracker.ietf.org/doc/draft-ounsworth-pq-composite-kem/<https://urldefense.com/v3/__https:/datatracker.ietf.org/doc/draft-ounsworth-pq-composite-kem/__;!!FJ-Y8qCqXTj2!YIF4pTdFL3liB7ZI4BJ-NrvMFacfpmCiyS3MBD7eCXaYK0lwgONuJ5iDuRufD2s3HKst3qn50lkcr0eU1uM$>



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.




Reply via email to