3. Chiffrement des messages push
3. Chiffrement des messages push
Le chiffrement d'un message push se déroule en quatre phases :
-
Un secret partagé est dérivé par ECDH [ECDH] (voir section 3.1 de ce document).
-
Le secret partagé est ensuite combiné avec le secret d'authentification pour produire la matière de clé d'entrée (IKM) utilisée dans [RFC8188] (voir section 3.3 de ce document).
-
Une clé de chiffrement de contenu et un nonce sont dérivés selon le processus de [RFC8188].
-
Le chiffrement ou le déchiffrement suit [RFC8188].
Le processus de dérivation des clés est résumé à la section 3.4. Les restrictions sur l'usage du codage de contenu chiffré sont décrites à la section 4.
3.1. Accord de clés Diffie-Hellman
Pour chaque nouvel abonnement que l'agent utilisateur crée pour une application, il génère également une paire de clés P-256 [FIPS186] pour ECDH [ECDH].
Lors de l'envoi d'un message push, le serveur d'application génère aussi une nouvelle paire de clés ECDH sur la même courbe P-256.
La clé publique ECDH du serveur d'application figure comme paramètre « keyid » dans l'en-tête du codage de contenu chiffré (voir section 2.1 de [RFC8188]).
Le serveur d'application combine sa clé privée ECDH avec la clé publique fournie par l'agent utilisateur selon [ECDH] ; à la réception du message push, l'agent utilisateur combine sa clé privée avec la clé publique du serveur d'application dans « keyid » de la même manière. Ces opérations produisent la même valeur de secret partagé ECDH.
3.2. Authentification des messages push
Pour garantir l'authentification correcte des messages push, un secret d'authentification symétrique est ajouté aux informations générées par l'agent utilisateur. Le secret d'authentification est mélangé dans le processus de dérivation de clé de la section 3.3.
Un agent utilisateur MUST générer et fournir une séquence de 16 octets difficile à deviner pour l'authentification des messages push. Elle SHOULD être produite par un générateur de nombres aléatoires cryptographiquement solide [RFC4086].
3.3. Combinaison des secrets partagé et d'authentification
Le secret partagé issu d'ECDH est combiné avec le secret d'authentification à l'aide de la fonction de dérivation de clé basée sur HMAC (HKDF) [RFC5869]. Cela produit la matière de clé d'entrée utilisée par [RFC8188].
HKDF utilise l'algorithme de hachage SHA-256 [FIPS180-4] avec les entrées suivantes :
salt : le secret d'authentification
IKM : le secret partagé dérivé par ECDH
info : la concaténation de la chaîne ASCII « WebPush: info » (sans octet NUL final), d'un octet zéro, de la clé publique ECDH de l'agent utilisateur et de la clé publique ECDH du serveur d'application (les deux clés publiques sont au format de point non compressé défini dans [X9.62]). Soit :
key_info = "WebPush: info" || 0x00 || ua_public || as_public
L : 32 octets (la sortie a la longueur de la sortie HMAC SHA-256 sous-jacente)
3.4. Synthèse du chiffrement
On obtient la clé de chiffrement de contenu finale et le nonce selon la séquence suivante, présentée ici en pseudo-code avec HKDF décomposé en étapes HMAC-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]
On omet ici le OU exclusif du nonce final avec le numéro de séquence d'enregistrement, car les messages push ne contiennent qu'un seul enregistrement (voir section 4) et le numéro de séquence du premier enregistrement est zéro.