I'd like to just add a supporting comment on this by showing what we've currently done.

At the moment KEM usage in the JCA is provided in the BC API by doing the following:

// key pair generation
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("Kyber", "BCPQC");
        kpg.initialize(KyberParameterSpec.kyber1024, new SecureRandom());

        KeyPair kp = kpg.generateKeyPair();

//kem usage
        KeyGenerator keyGen = KeyGenerator.getInstance("Kyber", "BCPQC");

//encapsulation step
        keyGen.init(new KEMGenerateSpec(kp.getPublic(), "AES"), new SecureRandom());

        SecretKeyWithEncapsulation secEnc1 = (SecretKeyWithEncapsulation)keyGen.generateKey();

//decapsulation step
        keyGen.init(new KEMExtractSpec(kp.getPrivate(), secEnc1.getEncapsulation(), "AES"));

        SecretKeyWithEncapsulation secEnc2 = (SecretKeyWithEncapsulation)keyGen.generateKey();

The above code will return an extension to SecretKey that has a getEncapsulation() method on it for "AES", with SecretKey.getEncoded() returning the actual shared secret. The result can either be used directly or getEncoded() might be called to provide a T value for a hybrid key agreement using ECCDH and then the destroy() method invoked. In the decapsulation step just SecretKey as a return would have been enough, but it just looked downright weird given how we were trying to do it and it seemed less confusing for developers if both ends produced the same result.

While this does mean we've got it to "fit" (it's basically the same pattern we used for the RSA-KEM in BCFIPS), it's clearly not portable and it does feel like we've stretched the API a bit much - the other init() methods now have to throw UnsupportedOperationException which does suggest this isn't really what the class is for. Some people have also shoehorned KEMs into KeyAgreement instead which, while it can be made to work, does also involve ignoring how the class is used normally and doing things like faking a public key. That it is even possible to do this multiple ways in the existing API, with neither working cleanly, does suggest that KEMs are a bit different from what we've seen before.

All that said, we are probably about 2 years out from when the first standards for these algorithms will appear and in some cases use of these algorithms will become mandatory. Now would be a really good time to have a universal solution that all of us can start supporting developed.

Thanks,
David


On 19/8/22 06:37, John Gray 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/

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