This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 24811 - Define how keys are derived from secret values for deriveKey
Summary: Define how keys are derived from secret values for deriveKey
Status: RESOLVED FIXED
Alias: None
Product: Web Cryptography
Classification: Unclassified
Component: Web Cryptography API Document (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Mark Watson
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-02-25 20:00 UTC by Mark Watson
Modified: 2014-02-28 02:08 UTC (History)
0 users

See Also:


Attachments

Description Mark Watson 2014-02-25 20:00:56 UTC
The deriveKey operation derives a key targeted at a specified algorithm. Both ECDH and DH algorithms output a Secret Value.

It is not yet specified how to map from the Secret Value to a key for the specified target algorithm.

It seems intuitive to use the "raw" import format for the target algorithm with the Secret Value as the raw input. If we do this we must define how to provide the length of the key and how to convert the secret value to that length. Presently, raw import for symmetric keys e.g. AES-GCM derives the key length from the provided data and fails if the provided data is not one of the supported lengths.

It seems valuable to be able to specify the length of the required key independently from the length of the Secret Value.

So, one possibility is to allow the length of the symmetric key to be specified as an input to the import operation and have that operation define the mapping from arbitrary length raw value to a key of the requested length. The deriveKey operations can then refer directly to the "raw" import operations for the derived key algorithm.
Comment 1 Mark Watson 2014-02-26 21:56:10 UTC
My suggestion from the mailing list:

However, there is one nit with algorithms like HKDF. HKDF (as defined in the RFC) takes as an input the length of the required keying material, L. It's not presently included in the HkdfCtrParams, presumably because, intuitively, you'd like it just to generate the right amount of keying material for the target derived key type (rather than have it generate more, that will just be truncated, or less, that will just fail).

So, if the length is only specified in the derived-key-algorithm-specific deriveKeyType, how does the key derivation algorithm (HKDF) access it ?

It seems that the required output length of the secret bits - which is equal to the required key length - needs to be available to the algorithm on which deriveKey is called. Whether you get there by truncation or by having that length as an input parameter depends on the algorithm ((EC)DH will do truncation, HKDF has an input parameter). But still, it makes intuitive sense for the length to be in the deriveKeyType parameter to the deriveKey method.

This gets worse when we consider HMAC. The intuitive thing to do to use HKDF to derive an HMAC key is the following:

p = deriveKey( { name: "HKDF", ... }, masterkey, { name: "HMAC", hash: "SHA-256" }, false, [ "sign", "verify" ] )

As with HMAC key generation, we expect the HMAC key length to default to the hash function block size. HKDF needs this number as an input.

The only way I can see to implement this pattern in the specification is to have text in each algorithm description which says "how to derive the required length for key derivation from derivedKeyType". So, for example, we might have in the deriveKey method:

- Let length be the result of running the "obtain derived key length" operation for the algorithm identified by derivedKeyType
- Let secret be the result of running the "derive key" operation for the algorithm identified in normalizedAlgorithm using length, ...
- Let result be the result of running the "import derived key" operation for the algorithm identified by derivedKeyType using secret

Then, in AES sections we would have:

Obtain derived Key Length
1. If any of the properties of AesDerivedKeyParams are not present in derivedKeyType, terminate ...
2. Return the value of the length property of derivedKeyType

In HMAC we would have:

Obtain derived Key Length
1. If the hash property HmacDerivedKeyParams is not present in derivedKeyType, terminate ...
2. If the length property of derivedKeyType is present, return the length property of derivedKeyType
3. Otherwise, return the block size of the hash algorithm identified by the hash property of derivedKeyType

In the (EC)DH section we would have:

Derive Key
... (all the steps to derive the secret value)
- If the number of bits in the secret value is less than length, terminate
- Otherwise, return the first length bits of secret value

And in the HKDF section we would have

Derive Key
- ...
- Perform the HKDF key derivation algorithm using length ...
- ...
Comment 2 Mark Watson 2014-02-27 01:55:38 UTC
In implementing this, it is clear that there is no need for separate derive key and derive bits operations. Only derive bits is required. This operation is then used directly by deriveBits. deriveKey will use the derive bits operation and then a raw import to create the Key.

derive bits always produces the requested number of bits.

deriveKey must discover from the algorithm for the desired key type what length is required. This requires a new 'derived key length' operation which determines this length.

For AES the derived key length operation simply returns the value of the length parameter.

For HMAC the derived key length returns the length parameter when specified, but otherwise the size of the block for the selected hash algorithm.
Comment 3 Mark Watson 2014-02-28 02:08:42 UTC
Changesets 417988dd96f7 and 1366fd7535ed

Define a new "Get key length" operation to obtain the required key length from the derived key algorithm (derivedKeyType parameter to deriveKey)
Remove separate derive key operation - both deriveKey and deriveBits methods will use the derive bits operation
Modify deriveKey procedures to obtain this length, pass it to the derive bits operation and then use "raw" import key to import the key to the derived key algorithm.