Hello all,
We are looking to add HKDF support as a KeyGenerator into OpenJDK
9. This will be available for general-purpose use. I've documented
the proposed API below.
RFE: https://bugs.openjdk.java.net/browse/JDK-8145255
Proof-of-concept implementation:
http://cr.openjdk.java.net/~jnimeh/reviews/8145255/webrev.1/
A set of new standard algorithm names would be created that define
the HMAC algorithm used with HKDF: HkdfSHA224, HkdfSHA256,
HkdfSHA384 and HkdfSHA512. We can at a later date include HKDF
variants that use other supported HMAC algorithms.
Instantiation:
--------------
In order to do HKDF derivations, a KeyGenerator of the appropriate
type must be obtained. This is done using one of the
KeyGenerator.getInstance methods, specifying the underlying HMAC
type using one of the names listed above.
Initialization:
---------------
The resulting HKDF KeyGenerator, in order to be compliant with the
KeyGenerator API, may be used to generate a key without any further
initialization. In this case, the Extract-then-Expand operation
will be performed using null salt and application-specific
information, and a random input key. The resulting output key will
be sized to the output length of the underlying HMAC. This can be
used as a way to obtain a random key.
The HKDF KeyGenerator supports all five flavors of the init
method. The resulting behavior differs between each flavor however.
KeyGenerator.init(SecureRandom):
--------------------------------
If this version of the init method is used, the KeyGenerator will
behave similarly to the default initialization, with the exception
that the caller may provide their own SecureRandom source for the
input key. A null value is allowed, in which case the
implementation will obtain the default SecureRandom implementation
for generating the input key.
KeyGenerator.init(int);
KeyGenerator.init(int, SecureRandom);
-------------------------------------
These two versions of the KeyGenerator allow the caller to provide
the resulting key length and, in the second case provide a
SecureRandom source. The caller must provide a non-negative length
value in bytes. A value of zero is allowed and returns a key of
the same length as the underlying HMAC. In both forms the
Extract-then-Expand operation will be performed with null salt and
application-specific information, and a random input key. If a
SecureRandom value is provided, its behavior is similar to
KeyGenerator.init(SecureRandom).
KeyGenerator.init(AlgorithmParameterSpec);
KeyGenerator.init(AlgorithmParameterSpec, SecureRandom);
--------------------------------------------------------
These versions of the init method allow the caller to customize the
input parameters to the HKDF generator as well as select the HKDF
function to perform.
Users desiring a specific HKDF function would initialize it using
one of three new AlgorithmParameterSpec classes:
HkdfExtractParameterSpec, HkdfExpandParameterSpec, or
HkdfParameterSpec. These three parameter spec classes are used to
initialize the HKDF key generator to perform the HKDF-Expand,
HKDF-Extract or a combination HKDF-Extract-then-Expand operation,
respectively.
The init(AlgorithmParameterSpec, SecureRandom) ignores the
SecureRandom parameter, and requires that input key material (IKM)
or a pseudorandom key (PRK) is provided.
Key Generation:
---------------
Once initialized (default or via one of the init methods) a key is
generated by calling KeyGenerator.generateKey().
The Specification:
------------------
Three new AlgorithmParameterSpec classes will be created to
initialize HKDF KeyGenerator objects:
HkdfParameterSpec: For performing the Extract-then-Expand operation
HkdfExtractParameterSpec: For performingthe HKDF-Extract operation
HkdfExpandParameterSpec: For performing the HKDF-Expand operation
/**
* Parameters for the Extract operation of the HMAC-based
Extract-and-Expand
* Key Derivation Function (HKDF). The HKDF function is defined in
* <a href="http://tools.ietf.org/html/rfc5869">RFC 5869</a>.
* This class is used to initialize KeyGenerators in the HKDF
family of
* generators, specifically for the HKDF Extract function.
* <p>
* Here is an example of how an HkdfExtractParameterSpec would be
used to
* initialize an HKDF KeyGenerator:
* <pre>
* byte[] salt;
* SecretKey inputKey;
* SecretKey resultingPRK;
*
* // salt and inputKey values populated with data
* ...
*
* // Get an instance of the HKDF KeyGenerator
* hkdfGen = KeyGenerator.getInstance("HkdfSHA256");
*
* // Create the spec object and use it to initialize the
generator.
* hkdfGen.init(new HkdfExtractParameterSpec(salt, inputKey));
*
* // Generate the PRK
* resultingPRK = hkdfGen.generateKey();
* </pre>
*
* @since 9
*/
public final class HkdfExtractParameterSpec implements
AlgorithmParameterSpec {
/**
* Constructs a new HkdfExtractParameterSpec with the given
salt value
* and key material
*
* @param salt the salt value, or {@code null} if not
specified. The
* contents of the array are copied to protect against
subsequent
* modification.
* @param inputKey the Input Keying Material (IKM).
*
* @throws NullPointerException if {@code inputKey} is {@code
null}.
*/
public HkdfExtractParameterSpec(byte[] salt, SecretKey inputKey);
/**
* Returns the Input Keying Material (IKM).
*
* @return the Input Keying Material.
*/
public SecretKey getIKM();
/**
* Returns the salt value.
*
* @return a copy of the salt value or {@code null} if no salt
was provided.
*/
public byte[] getSalt();
}
HkdfExpandParameterSpec:
------------------------
/**
* Parameters for the Expand operation of the HMAC-based
Extract-and-Expand
* Key Derivation Function (HKDF). The HKDF function is defined in
* <a href="http://tools.ietf.org/html/rfc5869">RFC 5869</a>.
* <p>
* Here is an example of how an HkdfExpandParameterSpec would be
used to
* initialize an HKDF KeyGenerator:
* <pre>
* byte[] info;
* SecretKey pseudoRandomKey;
* SecretKey resultingKey;
*
* // pseudoRandomKey and context info values populated with data
* ...
*
* // Get an instance of the HKDF KeyGenerator
* hkdfGen = KeyGenerator.getInstance("HkdfSHA256");
*
* // Create the spec object and use it to initialize the
generator.
* // Ask for a 64-byte key to be output.
* hkdfGen.init(new HkdfExpandParameterSpec(pseudoRandomKey,
info, 64));
*
* // Generate the key
* resultingKey = hkdfGen.generateKey();
* </pre>
*
* @since 9
*/
public final class HkdfExpandParameterSpec implements
AlgorithmParameterSpec {
/**
* Constructs a new HkdfExpandParameterSpec.
*
* @param prk the pseudorandom key used for HKDF-Expand.
* @param info optional context and application specific
information or
* {@code null} if no info data is provided. The contents
of the
* array are copied to protect against subsequent
modification.
* @param outLen the length in bytes of the output data
*
* @throws NullPointerException if {@code prk} is {@code null}.
* @throws IllegalArgumentException if {@code outLen} is a
* non-positive value.
*/
public HkdfExpandParameterSpec(SecretKey prk, byte[] info, int
outLen);
/**
* Returns a {@link SecretKey} object containing the
pseudorandom key (PRK).
*
* @return a {@link SecretKey} object containing the
pseudorandom key.
*/
public SecretKey getPRK();
/**
* Returns a copy of the context and application specific
information.
*
* @return a copy of the context and application specific
information.
* This may be {@code null} or empty if no specific
information was
* provided.
*/
public byte[] getInfo();
/**
* Returns the length in bytes of the output key to be produced.
*
* @return the length in bytes of the output key to be produced.
*/
public int getOutputLength();
}
HkdfParameterSpec:
------------------
/**
* Parameters for the combined Extract-then-Expand operation of the
HMAC-based
* Extract-and-Expand Key Derivation Function (HKDF). The HKDF
function
* is defined in <a href="http://tools.ietf.org/html/rfc5869">RFC
5869</a>.
* <p>
* Here is an example of how an HkdfParameterSpec would be used to
initialize
* an HKDF KeyGenerator:
* <pre>
* byte[] salt;
* byte[] info;
* SecretKey inputKey;
* SecretKey resultingKey;
*
* // salt, info and inputKey values populated with data
* ...
*
* // Get an instance of the HKDF KeyGenerator
* hkdfGen = KeyGenerator.getInstance("HkdfSHA256");
*
* // Create the spec object and use it to initialize the
generator.
* // Ask for a 64-byte key to be output.
* hkdfGen.init(new HkdfParameterSpec(inputKey, salt, info, 64));
*
* // Generate the key
* resultingKey = hkdfGen.generateKey();
* </pre>
*
* @since 9
*/
public final class HkdfParameterSpec implements
AlgorithmParameterSpec {
/**
* Constructs a new HkdfParameterSpec.
*
* @param inputKey the input keying material used for the
* HKDF-Extract-then-Expand operation.
* @param salt the salt value, or {@code null} if not
specified. The
* contents of the array are copied to protect against
subsequent
* modification.
* @param info optional context and application specific
information or
* {@code null} if no info data is provided. The contents
of the
* array are copied to protect against subsequent
modification.
* @param outLen the length in bytes of the output data
*
* @throws NullPointerException if {@code inputKey} is {@code
null}.
* @throws IllegalArgumentException if {@code outLen} is a
* non-positive value.
*/
public HkdfParameterSpec(SecretKey inputKey, byte[] salt,
byte[] info,
int outLen);
/**
* Returns the Input Keying Material (IKM).
*
* @return the Input Keying Material.
*/
public SecretKey getIKM();
/**
* Returns the salt value.
*
* @return a copy of the salt value or {@code null} if no salt
was provided.
*/
public byte[] getSalt();
/**
* Returns a copy of the context and application specific
information.
*
* @return a copy of the context and application specific
information.
* This may be {@code null} or empty if no specific
information was
* provided.
*/
public byte[] getInfo();
/**
* Returns the length in bytes of the output key to be produced.
*
* @return the length in bytes of the output key to be produced.
*/
public int getOutputLength();
}