[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Key derivation
> The OAKLEY draft discusses how to turn raw keying material into keys,
> and I'd suggest that you follow that method, which adds an extra byte
> to the keying material before generating a hash. It is important, I think,
> to have a uniform method for taking raw keying material (a varible length
> integer) and turning it into keys for a transform.
>
> I'd suggest that each transform come equipped with an interface for
> generating its key from a VPI input.
>
> Hilarie
I strongly support the approach suggested by Hilarie.
(I hope I understand it correctly).
In particular, I'd like to emphasize the rationale to this approach,
and some of the important issues, as I see them.
One can think of the key exchange protocol as providing a single key to the
communicating parties (we refer to that key as the "raw keying material"
or RKM). The individual keys required by specific transforms (DES, HMAC, etc)
are then derived from that RKM. An important issue is whether it is up to
the documents describing the individual transforms to define how a key
for that particular transform is derived from RKM or whether it is the
key exchange mechanism itself responsible for that key derivation.
I argue that the latter is the right approach.
Indeed the only way to achieve "computational independence" between keys
for different transforms is to have a unified mechanism defined by the
key exchange protocol
(By "computational independence" of the keys I mean that the compromise
of the key used by transform A will have no effect on the security of the
key used by transform B even if both keys were derived from the same RKM.
This property is needed not only in the case of explicit compromise but
to prevent cryptanalytical attacks based on dependencies between keys).
The main ingredient to achieve this computational independence is to
derive the per-algorithm keys by cryptographically combining the key RKM
with a *unique* identifier for the specific algorithm. Such unique identifiers
could be the IANA assigned numbers for the transforms (which are required
in any case for security parameter negotiation), or any other related encoding
(e.g., the IANA number repeated 17 times, etc.)
If this cryptographic copmbination is done, for example, through a strong
keyed hash, say, H(alg-id, RKM) then keys derived using different values
of alg-id should be computationally independent even if the same RKM is used.
(If, in contrast, one lets each transform define its own key material from RKM
then one could easily end with different transforms that derive the same
or related key bits. I can easily imagine seeing DES and HMAC-MD5 sharing
key bits, or 3DES-CBC and 3DES-CBC-MAC using the exact same key).
It is ok if a particular transform "requests" from the key exchange a
certain number of bits and then defines a way to expand this key (or apply
any other manipulation to it). As long as the basic key provided to this
transform is independent from the keys provided to other algorithms then
the internal work of one transform is irrelevant to the security of the
others.
Therefore, we see that the required "interface" between a transform and
the key exchange engine is a mechanism by which the transform specifies
the number of (pseudorandom) bits that it needs as key material.
(Another parameter in this interface is the cryptographic strength of these
bits, but this is a complex issue that I prefer not to discuss here.)
Since different transforms will request different numbers of key bits
we need the key exchange to support a well-defined mechanism to
derive such a variable number of key bits.
Two main approaches are:
-- Concatenate ouputs of the hash function computed using an increasing
counter:
H(algorithm-id, 0, RKM), H(algorithm-id, 1, RKM), H(algorithm-id, 2, RKM),.
..
for as many times as needed to get all the necessary bits
(e.g., if H is MD5 and the algorithm is 3DES you'll use counter with
0 and 1 to get 256 bits of output and then choose the first 192 bits).
-- Iterate on the derived keys.
For example, the first block of bits is derived by
K1 = H(algorithm-id, RKM), the second block by K2 = H(K1, RKM) etc.
Many variants exist, e.g. to use only part of the bits of K1, K2,...
for the derived key.
Two final remarks:
1) I used the example of keyed hash because it is very popular these days.
In general when deriving keys (or pseudorandom strings) one should be talking
about pseudorandom functions (not just keyed hashing).
Not only is this term a more accurate one but, more importantly,
it includes many functions which are NOT keyed hash functions.
For example, it is perfectly correct (and probably *more secure*)
to use 3DES as the derivation algorithm instead of a keyed hash.
Similarly, any other block cipher (like IDEA) can be used
for key derivation, even if these ciphers are NOT keyed hash functions.
One more advantage of the notion of pseudorandom functions
is that it makes very clear the distinction between keys
and arguments to the function. This distinction is less clear in
keyed hash functions and a good source for design mistakes.
(Fortunately, Oakley already incorporate the pseudorandom function -- prf --
terminolgy.)
2) Using alg-id to get key independence may not always be sufficient.
For example, one may have the need to derive keys for a version of RC5
with 12 rounds and another for RC5 with 20 rounds. In that case, again,
the keys need to be independent, and the number of rounds reflected,
or added, to the alg-id identifier.
Similarly, one may need to derive two independent keys for the *same*
algorithm (e.g., DES used to conceal identities and DES used to encrypt
data). In such a case a differentiation via different alg-id values
or additional information is necessary.
Hugo