3. Push Message Encryption
3. Push Message Encryption
Push message encryption happens in four phases:
-
A shared secret is derived using ECDH [ECDH] (see Section 3.1 of this document).
-
The shared secret is then combined with the authentication secret to produce the input keying material (IKM) used in [RFC8188] (see Section 3.3 of this document).
-
A content encryption key and nonce are derived using the process in [RFC8188].
-
Encryption or decryption follows according to [RFC8188].
The key derivation process is summarized in Section 3.4. Restrictions on the use of the encrypted content coding are described in Section 4.
3.1. Diffie-Hellman Key Agreement
For each new subscription that the user agent generates for an application, it also generates a P-256 [FIPS186] key pair for use in ECDH [ECDH].
When sending a push message, the application server also generates a new ECDH key pair on the same P-256 curve.
The ECDH public key for the application server is included as the "keyid" parameter in the encrypted content coding header (see Section 2.1 of [RFC8188]).
An application server combines its ECDH private key with the public key provided by the user agent using the process described in [ECDH]; on receipt of the push message, a user agent combines its private key with the public key provided by the application server in the "keyid" parameter in the same way. These operations produce the same value for the ECDH shared secret.
3.2. Push Message Authentication
To ensure that push messages are correctly authenticated, a symmetric authentication secret is added to the information generated by a user agent. The authentication secret is mixed into the key derivation process described in Section 3.3.
A user agent MUST generate and provide a hard-to-guess sequence of 16 octets that is used for authentication of push messages. This SHOULD be generated by a cryptographically strong random number generator [RFC4086].
3.3. Combining Shared and Authentication Secrets
The shared secret produced by ECDH is combined with the authentication secret using the HMAC-based key derivation function (HKDF) [RFC5869]. This produces the input keying material used by [RFC8188].
The HKDF function uses the SHA-256 hash algorithm [FIPS180-4] with the following inputs:
salt: the authentication secret
IKM: the shared secret derived using ECDH
info: the concatenation of the ASCII-encoded string "WebPush: info" (this string is not NUL-terminated), a zero octet, the user agent ECDH public key, and the application server ECDH public key, (both ECDH public keys are in the uncompressed point form defined in [X9.62]. That is:
key_info = "WebPush: info" || 0x00 || ua_public || as_public
L: 32 octets (i.e., the output is the length of the underlying SHA-256 HMAC function output)
3.4. Encryption Summary
This results in a final content encryption key and nonce generation using the following sequence, which is shown here in pseudocode with HKDF expanded into separate discrete steps using HMAC with SHA-256:
-- For a user agent:
ecdh_secret = ECDH(ua_private, as_public)
auth_secret = random(16)
salt = <from content coding header>
-- For an application server:
ecdh_secret = ECDH(as_private, ua_public)
auth_secret = <from user agent>
salt = random(16)
-- For both:
## Use HKDF to combine the ECDH and authentication secrets
# HKDF-Extract(salt=auth_secret, IKM=ecdh_secret)
PRK_key = HMAC-SHA-256(auth_secret, ecdh_secret)
# HKDF-Expand(PRK_key, key_info, L_key=32)
key_info = "WebPush: info" || 0x00 || ua_public || as_public
IKM = HMAC-SHA-256(PRK_key, key_info || 0x01)
## HKDF calculations from RFC 8188
# HKDF-Extract(salt, IKM)
PRK = HMAC-SHA-256(salt, IKM)
# HKDF-Expand(PRK, cek_info, L_cek=16)
cek_info = "Content-Encoding: aes128gcm" || 0x00
CEK = HMAC-SHA-256(PRK, cek_info || 0x01)[0..15]
# HKDF-Expand(PRK, nonce_info, L_nonce=12)
nonce_info = "Content-Encoding: nonce" || 0x00
NONCE = HMAC-SHA-256(PRK, nonce_info || 0x01)[0..11]
Note that this omits the exclusive-OR of the final nonce with the record sequence number, since push messages contain only a single record (see Section 4) and the sequence number of the first record is zero.