Skip to content

JSON Web Encryption Key Ladder Key Exchange

Wesley Miaw edited this page Jul 15, 2016 · 4 revisions

The JSON Web Encryption (JWE) key ladder uses the Web Crypto API unwrap function for key exchange. The keying material is specified within a JSON Web Key (JWK) that specifies algorithm, usage, and extractable attributes. The JWK is then wrapped into a JWE structure. This combination will be referred to as JWE+JWK. All keys are marked non-extractable.

When coupled with the pre-shared keys Kpw or model group keys Kdw wrapping key, this scheme guarantees that key exchange is being performed for the requesting entity but does not provide perfect forward secrecy.

Unlike other key exchange schemes, the key ladder returns three keys: an AES-128-KeyWrap wrapping key Kwrap, an AES-128-CBC session encryption key Kenc, and an HMAC-SHA256 session HMAC key Khmac. Kwrap will be wrapped using AESWrap with Kpw, Kdw, or a previously issued Kwrap. The session keys Kenc and Khmac will be wrapped using AESWrap with Kwrap.

An intermediate wrapping key Kwrap is used to limit the use of a single wrapping key for all unwrap operations in much the same way as the session keys are time-limited to restrict their usage. Use of a previously issued Kwrap instead of Kpw or Kdw is likely to be more efficient as the Kpw and Kdw keys require a higher level of security due to their permanent nature.

The master token entity is expected to persist the wrapping key and wrap data for use in the next key exchange.

This scheme is identified by the string JWE_LADDER.

N.B. This scheme does not provide perfect forward secrecy and should only be used when it is necessary to satisfy other security requirements.

Key Request Data

keydata = {
  "#mandatory" : [ "mechanism" ],
  "mechanism" : "enum(PSK|MGK|WRAP)",
  "wrapdata" : "binary",
}
Field Description
mechanism mechanism for wrapping and unwrapping the new wrapping key
wrapdata wrapped previous Kwrap

Mechanism

The PSK and MGK mechanisms indicate the wrapping key returned in the response should be wrapped with Kpw or Kdw. The WRAP mechanism indicates the wrapping key returned in the response should be wrapped with a previous Kwrap, which will be provided to the responding entity by including the wrap data.

Wrap Data

When using the WRAP mechanism, the wrap data will be included and is a previously issued key Kwrap wrapped using AESWrap with an AES-128-KeyWrap key Kissuer only known by responding entity (or entities in a trusted services network). The responding entity is capable of unwrapping the wrap data to retrieve the previously issued key Kwrap and therefore does not need to remember all Kwrap keys it has issued.

Since Kissuer allows access to all generated session keys, it should be sufficiently protected and periodically rotated. Kissuer must not be available to the requesting entity.

See the response wrap data definition below.

Key Response Data

keydata = {
  "#mandatory" : [ "wrapkey", "wrapdata", "encryptionkey", "hmackey" ],
  "wrapkey" : "binary",
  "wrapdata" : "binary",
  "encryptionkey" : "binary",
  "hmackey" : "binary",
}
Field Description
encryptionkey JWE+JWK wrapped new Kenc
hmackey JWE+JWK wrapped new Khmac
wrapdata Kissuer-wrapped new Kwrap
wrapkey JWE+JWK wrapped new Kwrap

Wrap Key & Wrap Data

The new wrapping key Kwrap is wrapped using AESWrap using the wrapping key identified in the request: Kpw for PSK, Kdw for MGK, or a previously issued Kwrap for WRAP. The wrap data contains the new wrapping key Kwrap wrapped using AESWrap with Kissuer only known by the responding entity (or entities in a trusted services network).

Wrap Key & Wrap Data Pseudocode

switch (request.mechanism) {
  case PSK:  Kprev = Kpw; break;
  case MGK:  Kprev = Kdw; break;
  case WRAP: Kprev = unwrap(Kissuer, request.wrapData); break;
}
Kwrap = generateRandomKey(128);
response.wrapKey = wrap(Kprev, Kwrap);
response.wrapData = wrap(Kissuer, Kwrap);

Encryption & HMAC Keys

The encryption and HMAC keys are wrapped using AESWrap with the new wrapping key Kwrap.

Encryption & HMAC Key Pseudocode

encryptionKey = generateRandomKey(128);
hmacKey = generateRandomKey(256);
response.encryptionKey = wrap(Kwrap, encryptionKey);
response.hmacKey = wrap(Kwrap, hmacKey);

Example Key Exchange

The following sequence diagram illustrates a sequence of key exchanges. Only the key request data and key response data is documented.

Clone this wiki locally