Dérivation de sous-clé et chiffrement authentifié dans ASP.NET Core
La plupart des clés de l’anneau de clés contiennent une forme d’entropie et ont des informations algorithmiques indiquant « Chiffrement en mode CBC + validation HMAC » ou « Chiffrement GCM + validation ». Dans ce cas, nous faisons référence à l’entropie incorporée en tant que KM (code de chiffrement, Keying Material) principal pour cette clé, et nous effectuons une fonction de dérivation de clés pour dériver les clés qui seront utilisées pour les opérations de chiffrement.
Notes
Les clés sont abstraites et une implémentation personnalisée peut ne pas se comporter comme ci-dessous. Si la clé fournit sa propre implémentation de IAuthenticatedEncryptor
plutôt que d’utiliser l’une de nos usines intégrées, le mécanisme décrit dans cette section ne s’applique plus.
Dérivation de sous-clé et de données authentifiées supplémentaires
L’interface IAuthenticatedEncryptor
sert d’interface principale pour toutes les opérations de chiffrement authentifiées. Sa méthode Encrypt
prend deux mémoires tampons : texte en clair et additionalAuthenticatedData (AAD). Le flux de contenu en texte clair n’a pas modifié l’appel à IDataProtector.Protect
, mais l’AAD est généré par le système et se compose de trois composants :
L’en-tête magique 09 F0 C9 F0 32 bits qui identifie cette version du système de protection des données.
L’ID de clé 128 bits.
Chaîne de longueur variable formée à partir de la chaîne d’objectif qui a créé le
IDataProtector
qui effectue cette opération.
Étant donné que l’AAD est unique pour le tuple des trois composants, nous pouvons l’utiliser pour dériver de nouvelles clés à partir de KM au lieu d’utiliser KM lui-même dans toutes nos opérations de chiffrement. Pour chaque appel à IAuthenticatedEncryptor.Encrypt
, le processus de dérivation de clé suivant a lieu :
( K_E, K_H ) = SP800_108_CTR_HMACSHA512(K_M, AAD, contextHeader || keyModifier)
Ici, nous appelons le KDF NIST SP800-108 en mode compteur (voir NIST SP800-108, sec. 5.1) avec les paramètres suivants :
Clé de dérivation de clé (KDK) =
K_M
PRF = HMACSHA512
label = additionalAuthenticatedData
context = contextHeader || keyModifier
L’en-tête de contexte est de longueur variable et sert essentiellement d’empreinte numérique des algorithmes pour lesquels nous dérivons K_E
et K_H
. Le modificateur de clé est une chaîne 128 bits générée de manière aléatoire pour chaque appel à Encrypt
et sert à garantir avec une probabilité écrasante que KE et KH sont uniques pour cette opération de chiffrement d’authentification spécifique, même si toutes les autres entrées dans le KDF sont constantes.
Pour les opérations de chiffrement en mode CBC + validation HMAC, | K_E |
correspond à la longueur de la clé de chiffrement par blocs symétrique et | K_H |
est la taille de synthèse de la routine HMAC. Pour les opérations de chiffrement GCM + validation, | K_H | = 0
.
Chiffrement en mode CBC + validation HMAC
Une fois K_E
généré via le mécanisme ci-dessus, nous générons un vecteur d’initialisation aléatoire et nous exécutons l’algorithme de chiffrement par blocs symétriques pour chiffrer le texte en clair. Le vecteur d’initialisation et le texte de chiffrement sont ensuite exécutés via la routine HMAC initialisée avec la clé K_H
pour produire le MAC. Ce processus et la valeur renvoyée sont représentés graphiquement ci-dessous.
output:= keyModifier || iv || E_cbc (K_E,iv,data) || HMAC(K_H, iv || E_cbc (K_E,iv,data))
Remarque
L’implémentation IDataProtector.Protect
ajoute l’en-tête magique et l’ID de clé à la sortie avant de le renvoyer à l’appelant. Étant donné que l’en-tête magique et l’ID de clé font implicitement partie d’AAD, et que le modificateur de clé est alimenté en tant qu’entrée dans le KDF, cela signifie que chaque octet de la charge utile finale retournée est authentifié par le MAC.
Chiffrement Galois/Counter Mode + validation
Une fois K_E
généré via le mécanisme ci-dessus, nous générons une valeur nonce aléatoire de 96 bits et nous exécutons l’algorithme de chiffrement par blocs symétriques pour déchiffrer le texte en clair et produire la balise d’authentification 128 bits.
output := keyModifier || nonce || E_gcm (K_E,nonce,data) || authTag
Remarque
Même si GCM prend en charge en mode natif le concept d’AAD, nous alimentons toujours AAD uniquement au KDF d’origine, en choisissant de transmettre une chaîne vide dans GCM pour son paramètre AAD. Il y a deux raisons à cela. Tout d’abord, pour prendre en charge l’agilité, nous ne voulons jamais utiliser K_M
directement comme clé de chiffrement. En outre, GCM impose des exigences d’unicité très strictes à ses entrées. La probabilité que la routine de chiffrement GCM soit appelée sur au moins deux ensembles distincts de données d’entrée avec la même paire (clé, nonce) ne doit pas dépasser 2^-32. Si nous corrigeons K_E
, nous ne pouvons pas effectuer plus de 2^32 opérations de chiffrement avant d’exécuter des dépassements de la limite 2^-32. Cela peut sembler être un très grand nombre d’opérations, mais un serveur web à trafic élevé peut passer par 4 milliards de demandes en quelques jours, ce qui s’inscrit dans la durée de vie normale de ces clés. Pour rester conforme à la limite de probabilité 2^-32, nous continuons à utiliser un modificateur de clé de 128 bits et un nonce 96 bits, ce qui étend radicalement le nombre d’opérations utilisables pour un élément donné K_M
. Par souci de simplicité de conception, nous partageons le chemin de code KDF entre les opérations CBC et GCM, et étant donné qu’AAD est déjà pris en compte dans le KDF, il n’est pas nécessaire de le transférer à la routine GCM.