Draft design for Key Derivation API

Michael StJohns mstjohns at comcast.net
Tue Nov 7 01:25:08 UTC 2017


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










More information about the security-dev mailing list