3. Crittografia dei messaggi push
3. Crittografia dei messaggi push
La crittografia di un messaggio push avviene in quattro fasi:
-
Si deriva un segreto condiviso usando ECDH [ECDH] (vedere Sezione 3.1 di questo documento).
-
Il segreto condiviso è poi combinato con l'authentication secret per produrre l'input keying material (IKM) usato in [RFC8188] (vedere Sezione 3.3 di questo documento).
-
Una content encryption key e un nonce sono derivati con il processo in [RFC8188].
-
La crittografia o decifratura segue [RFC8188].
Il processo di derivazione delle chiavi è riassunto nella Sezione 3.4. Le restrizioni sull'uso della codifica di contenuto crittografata sono nella Sezione 4.
3.1. Accordo di chiave Diffie-Hellman
Per ogni nuova subscription che l'user agent genera per un'applicazione, genera anche una coppia di chiavi P-256 [FIPS186] per ECDH [ECDH].
Quando invia un messaggio push, l'application server genera anche una nuova coppia di chiavi ECDH sulla stessa curva P-256.
La chiave pubblica ECDH dell'application server è inclusa come parametro « keyid » nell'intestazione della codifica di contenuto crittografata (vedere Sezione 2.1 di [RFC8188]).
L'application server combina la sua chiave privata ECDH con la chiave pubblica fornita dall'user agent usando il processo in [ECDH]; alla ricezione del messaggio push, l'user agent combina la sua chiave privata con la chiave pubblica dell'application server nel parametro « keyid » allo stesso modo. Queste operazioni producono lo stesso valore per il segreto condiviso ECDH.
3.2. Autenticazione dei messaggi push
Per garantire che i messaggi push siano autenticati correttamente, si aggiunge un authentication secret simmetrico alle informazioni generate dall'user agent. L'authentication secret è mescolato nel processo di derivazione delle chiavi della Sezione 3.3.
Un user agent MUST generare e fornire una sequenza di 16 ottetti difficile da indovinare usata per l'autenticazione dei messaggi push. SHOULD essere generata da un generatore di numeri casuali crittograficamente robusto [RFC4086].
3.3. Combinazione dei segreti condiviso e di autenticazione
Il segreto condiviso prodotto da ECDH è combinato con l'authentication secret usando la funzione di derivazione delle chiavi basata su HMAC (HKDF) [RFC5869]. Ciò produce l'input keying material usato da [RFC8188].
HKDF usa l'algoritmo di hash SHA-256 [FIPS180-4] con i seguenti input:
salt: l'authentication secret
IKM: il segreto condiviso derivato con ECDH
info: la concatenazione della stringa ASCII « WebPush: info » (senza terminatore NUL), di un ottetto zero, della chiave pubblica ECDH dell'user agent e della chiave pubblica ECDH dell'application server (entrambe nel formato di punto non compresso definito in [X9.62]). Cioè:
key_info = "WebPush: info" || 0x00 || ua_public || as_public
L: 32 ottetti (l'output ha la lunghezza dell'output HMAC SHA-256 sottostante)
3.4. Riepilogo della crittografia
Si ottiene la content encryption key finale e la generazione del nonce con la sequenza seguente, qui in pseudocodice con HKDF espanso in passi discreti con 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]
Si omette qui lo XOR esclusivo del nonce finale con il numero di sequenza del record, poiché i messaggi push contengono un solo record (vedere Sezione 4) e il numero di sequenza del primo record è zero.