On 11/3/2017 4:59 PM, Jamil Nimeh wrote:
Hello all,

This is a review request for the draft of a new Key Derivation API.  The goal of this API will be to provide a framework for KDF algorithms like HKDF, TLS-PRF, PBKDF2 and so forth to be publicly accessible.  We also plan to provide an SPI that let 3rd parties create their own implementations of KDFs in their providers, rather than trying to force them into KeyGenerators, SecretKeyFactories and the like.

Rather than stuff this email full of the specification text (since it is likely to get quite a few iterations of comments and comments-to-comments), I have placed the API both in simple text form and as a Javadoc at the following locations:

spec: http://cr.openjdk.java.net/~jnimeh/reviews/kdfspec/kdfspec.01.txt

javadoc: http://cr.openjdk.java.net/~jnimeh/reviews/kdfspec/javadoc.01/

They're both the same content, just use whichever is friendlier for your eyes.

In addition, I have opened up the JEP as well:

https://bugs.openjdk.java.net/browse/JDK-8189808

Thanks to those who have contributed to very early internal drafts of this so far, and thanks in advance to those who will be contributing comments going forward.

--Jamil


Most of the following suggestions (and please take them as such regardless of any directive language) represent things I've had to do manually that I'd really prefer to do in a real key derivation API.  A few are related to how to keep things securely stored in an HSM.

Add a .reset() method to KeyDerivation.  Call this to clear the state of the KDF.

Add an .initialize(List<DerivationParameterSpec>, SecretKey masterSecret) method.  Remove the argument to deriveKey and deriveKeys.  This plays with the stuff to follow, but basically, a KDF may need all of the per-key derivation input to calculate the total length of the output key stream as an internal input to the KDF before ever emitting a single key.   Also - how exactly were you planning on keying the KDF?  I guess you could pass that in in the KeyDerivation.getInstance() call or as part of the algorithmParameter but.... probably makes more sense to keep the KDF instance key-free to allow for reuse.

Rename DerivedKeyParameterSpec to DeriviationParameterSpec and provide an algorithm name for "IV" or "Cleartext".  See below for .deriveData()

deriveKey() emits the next key in the sequence using the data stream to key conversion rules.

deriveKeys() emits as many keys left in the stream to the next data derivation or the defined end of stream based on the input specs.  deriveKeys(int num) derives the next num keys.

Add a .deriveData() with a return class of byte[].   This gets a portion of the derived data stream in the clear. E.g. an IV.

Add a .deriveObject() with a return class of Object.  The returned object may not be an instance of java.security.Key.  This takes the derived data stream and converts it into the object type specified by the derivation parameter.  In a hardware security module, this might be a reference to a secured set of data or even an confidential IV.

All of the derive methods throw an InvalidParameterSpecException if the next derivation parameter doesn't match the calling method (e.g. trying to deriveData when the parameter spec says emit a key).

In KeyDerivation, change the output class of the deriveKey to java.security.Key; similar for deriveKeys change the output to List<Key>.   Basically, its possible to use the output of a KDF stream to derive private keys and this should be supported. It's occasionally helpful (but not very often) for two devices to share a key pair that they create through a key agreement process (e.g. two HSMs acting as backup to each other).  Alternately, consider adding a "public KeyPair deriveKeyPair()" method.

Consider adding a marker interface  javax.crypto.MasterSecret (subclass of javax.crypto.SecretKey) and using that as class for the initialize call argument.

I'm happy to provide an edited .java file with these proposed changes - but not until at least next Monday; I'm on travel.

Mike







Reply via email to