<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <p>Hi Mike, thank you for your comments and feedback.  I have a few
      comments and questions inline:<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 11/06/2017 05:25 PM, Michael StJohns
      wrote:<br>
    </div>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite">On 11/3/2017 4:59 PM, Jamil Nimeh wrote: <br>
      <blockquote type="cite">Hello all, <br>
        <br>
        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. <br>
        <br>
        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: <br>
        <br>
        spec: <a class="moz-txt-link-freetext"
href="http://cr.openjdk.java.net/%7Ejnimeh/reviews/kdfspec/kdfspec.01.txt">http://cr.openjdk.java.net/~jnimeh/reviews/kdfspec/kdfspec.01.txt</a>
        <br>
        <br>
        javadoc: <a class="moz-txt-link-freetext"
          href="http://cr.openjdk.java.net/%7Ejnimeh/reviews/kdfspec/javadoc.01/">http://cr.openjdk.java.net/~jnimeh/reviews/kdfspec/javadoc.01/</a>
        <br>
        <br>
        They're both the same content, just use whichever is friendlier
        for your eyes. <br>
        <br>
        In addition, I have opened up the JEP as well: <br>
        <br>
        <a class="moz-txt-link-freetext"
          href="https://bugs.openjdk.java.net/browse/JDK-8189808">https://bugs.openjdk.java.net/browse/JDK-8189808</a>
        <br>
        <br>
        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. <br>
        <br>
        --Jamil <br>
        <br>
        <br>
      </blockquote>
      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. <br>
      <br>
      Add a .reset() method to KeyDerivation.  Call this to clear the
      state of the KDF. <br>
      <br>
      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. <br>
    </blockquote>
    Well, let's get the easy one out of the way.  As you suspected I
    planned to pass the SecretKey in via AlgorithmParameterSpec.  The
    three classes unfortunately didn't show that.  Maybe on the next
    iteration I can put an HkdfParameterSpec in there just as a sample
    so folks can see that where the key comes in.  The reason I went
    that way was because the goal was to provide all algorithm paramters
    at instantiation time, and the SecretKey was just another input.  I
    don't know if just making the KDF key-free would be enough for
    reuse, at least not for all cases.  Thinking about HKDF and TLS 1.3
    for instance, the key is the same for a collection of keys (like the
    client and server app traffic master keys that come from the master
    secret, for instance) - what changes are the other inputs to HKDF.<br>
    <br>
    One issue that came up on an early internal rev of the API was that
    we didn't want to separate instantiation and initialization, so all
    the inputs to the KDF now come in at getInstance time through
    AlgorithmParameterSpecs, rather than doing getInstance/init/... like
    KeyAgreement does.  I wonder if it would be OK to still have an init
    (and a reset as you wanted) method so we can provide new inputs
    top-to-bottom into the KDF object.  All the getInstance forms would
    stay more or less the same, so there's no way to make a KDF object
    without it being in an initialized state.  But when you need new
    inputs you don't have to make a new object.  I like being able to
    reuse the object and reset it to its starting state.  I don't know
    if the folks that brought up the instance/init issue would have a
    problem with that.  I think we're still adhering to the spirit of
    what they wanted to see since getInstance still gives you a fully
    initialized object.<br>
    <br>
    That's a bit different than what you're talking about with your
    initialize method, I kinda birdwalked a bit.  Let me ask a couple
    questions: When you proposed initialize(), were you envisioning that
    applications would always need to call it before derive*?  Or did
    you really mean "may" and an implementation would have to go back
    and generate more material if they exhausted everything they knew
    about?  Given your changes to deriveKey(s) it looked more like you
    intended to know the total length up-front, since there's no other
    way to say some arbitrary next key is of a specific length with no
    argument to deriveKey[s].<br>
    <br>
    If you did want the total length of all keys/data/objects to be
    supplied before derivation, what if we were to supply that to the
    getInstance calls?  A similar idea was put forth internally, but we
    decided to hold off on it and wait for some feedback from the
    field.  So if we were to go this route then getInstance calls might
    look like this:<br>
    <br>
    public static KeyDerivation getInstance(String alg,
    AlgorithmParameterSpec params, List<DerivationParameterSpec>
    deriveParams);<br>
    public static KeyDerivation getInstance(String alg, String provider,
    AlgorithmParameterSpec params, List<DerivationParameterSpec>
    deriveParams);<br>
    public static KeyDerivation getInstance(String alg, Provider
    provider, AlgorithmParameterSpec params,
    List<DerivationParameterSpec> deriveParams);<br>
    <br>
    You end up with a ready-to-use KDF right from the get-go.<br>
    <br>
    If we're going that route though, *and* we try to make it reusable,
    then we have to specify both KDF parameters and derivation
    parameters in an initialize call.  If reusability isn't all that
    important then we don't have reset and initialize and you just make
    a new KDF every time.  I like the former approach better, myself -
    though I would like to know how others feel about it.<br>
    <br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      Rename DerivedKeyParameterSpec to DeriviationParameterSpec and
      provide an algorithm name for "IV" or "Cleartext".  See below for
      .deriveData() <br>
    </blockquote>
    I think we could do that.  Those don't sound like names that would
    be a problem.  But maybe we go with an even more generic name like
    "data" or "raw".  Cleartext sounds too much like
    plaintext/ciphertext kind of lingo and IV is use specific.<br>
    <br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      deriveKey() emits the next key in the sequence using the data
      stream to key conversion rules. <br>
      <br>
      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. <br>
    </blockquote>
    Minor clarification: "...emits as many keys left in the stream to
    the next data <i><b>or Object</b></i> derivation" (I'm asking, not
    stating, just making sure I understand what you intended).<br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      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. <br>
      <br>
      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. <br>
    </blockquote>
    Again, just want to make sure I understand fully: So in a case where
    I want a given output to be an Object, I would provide a
    DerivationParameterSpec with an alg of..."Object" (?), a byte
    length, and Object-specific parameters provided through the "params"
    argument to the DPS?<br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      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). <br>
    </blockquote>
    Makes sense to me.  Are you OK with IllegalStateException when you
    try to derive a key after all elements in
    List<DerivationParameterSpec> have been previously returned?<br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      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. <br>
    </blockquote>
    Changing the output to Key makes sense.  For the HSM to HSM use case
    you're mentioning, that seems better suited to the KeyAgreement API,
    wouldn't it?<br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      Consider adding a marker interface  javax.crypto.MasterSecret
      (subclass of javax.crypto.SecretKey) and using that as class for
      the initialize call argument. <br>
    </blockquote>
    Maybe OBE since I'm proposing to pass the secret through the
    AlgorithmParameterSpec.  If not, I would recommend not subclassing
    it from SecretKey.  The Secret won't always be a key.  For an alg
    like PBKDF2 it would be a password.<br>
    <blockquote
      cite="mid:f26e9f65-5c65-4a88-0d17-5e57cf887b8f@comcast.net"
      type="cite"> <br>
      I'm happy to provide an edited .java file with these proposed
      changes - but not until at least next Monday; I'm on travel. <br>
      <br>
      Mike <br>
    </blockquote>
    Let me know your thoughts on this and maybe I can cook up another
    rev of the spec/javadoc.  Thanks again for the feedback!<br>
    <br>
    --Jamil<br>
    <br>
    <br>
  </body>
</html>