La diversification des clefs symétriques
La diversification (ou dérivation) est un procédé cryptographique permettant, à partir d’une clef symétrique, de générer une seconde clef.
Le procédé ne doit pas permettre, à partir de la seconde clef de retrouver la clef d’origine.
Utilisation en NFC
En NFC, la plupart du temps, les algorithmes utilisés sont symétriques (sauf pour les transactions bancaires). Les PICC ayant la capacité de gérer des algorithmes asymétriques sont plus chères et l’utilisation même de ce type d’algorithme demande plus de temps, ce qui n’est pas compatible avec la majorité des usages NFC. L’illustration la plus courante étant le contrôle d’accès qui nécessite un grand volume de contrôle en un temps très réduit (l’arrivée au boulot le matin des 2500 personnes).
Mais l’utilisation d’algorithmes symétriques pose un problème. En effet, si l’une des PICC est dérobée et que sa clef est cassée, ce sont toutes les PICC qui sont corrompues puisque la clef est la même partout.
Pour pallier à ce problème, on met en place une diversification des clefs.
La diversification est un processus décrit dans les documents “NIST-800-108” et “NIST-SP-800-38B“. En NFC, et en particulier pour les cartes sans contacts il existe deux standards décrit dans les “Application Note” AN0148 et AN10922.
Un projet est également disponible sur GitHub pour aider à la mise en oeuvre.
Comment ça marche ?
C’est très simple 🙂
La clef d’origine est passée dans un algorithme de diversification qui utilise des données du support (la PICC) pour générer une seconde clef. Les données utilisées sont en général, l’ID de la PICC, l’identifiant de l’application qui stocke la clef etc.
En sortie, la clef diversifiée ne permet pas, même en connaissant l’algorithme utilisé, de reconstruire la clef d’origine.
Du coup, si la clef d’une carte est corrompue, elle ne met plus en péril les autres cartes car elles ne possèdent pas les mêmes clefs.
Les applications qui doivent accéder à la carte connaissent la clef d’origine et font une diversification identique pour connaître la clef de la carte à utiliser.
Standard AN0148
Le standard AN0148 décrit la diversification à l’aide des algorithmes DES, 3DES et AES.
Les données utilisées pour diversifier les clefs sont l’ID de la PICC et l’index de la clef à diversifier.
DES
1 |
Kd = Edes(Km, (KeyNo||ID) xor Km) |
Ou:
- Kd = Clef diversifiée
- Km = Clef d’origine
- KeyNo = Index de la clef
- ID = Identifiant de la PICC
- Edes = Méthode de chiffrement DES
- xor = Méthode “Ou Exclusif”
- || = Méthode de concaténation
Vous pouvez expérimenter cette diversification avec le projet GitHub et les arguments :
1 2 3 4 5 6 7 8 |
mvn exec:java -Dstandard=AN0148_DES -Duid=04000000000000 -Dkey=0011223344556677 -DkeyIndex=1 ====== AN0148 DIVERSIFICATION ====== K: 00 11 22 33 44 55 66 77 ALGO: DES M: 01 04 00 00 00 00 00 00 K': C9 EE 53 B3 0B 51 08 76 ==================================== Diversified key: C9 EE 53 B3 0B 51 08 76 |
3DES
En 3DES, le procédé est similaire, on découpe la clef 3DES de 16 octets en 2 clefs de 8 octets qui sont chacun dérivées. La première partie avec les données de dérivation, la seconde partie avec les 8 premiers octets de la première diversification.
1 2 3 |
Kd0-7 = E3des(Km, ((KeyNo||ID) xor Km0-7)) Kd8-15 = E3des(Km, (Kd0-7 xor Km8-15)) Kd = Kd0-7 || Kd8-15 |
Ou:
- Kd = Clef diversifiée
- Km = Clef d’origine
- Km0-7 = 8 premiers octets de la clef d’origine
- Km8-15 = 8 derniers octets de la clef d’origine
- Kd0-7 = 8 premiers octets de la clef diversifiée
- Kd8-15 = 8 derniers octets de la clef diversifiée
- KeyNo = Index de la clef
- ID = Identifiant de la PICC
- E3des = Méthode de chiffrement 3DES
- xor = Méthode “Ou Exclusif”
- || = Méthode de concaténation
Vous pouvez expérimenter cette diversification avec le projet GitHub et les arguments :
1 2 3 4 5 6 7 8 |
mvn exec:java -Dstandard=AN0148_3DES -Duid=04112233445566 -Dkey=00112233445566778899AABBCCDDEEFF -DkeyIndex=1 ====== AN0148 DIVERSIFICATION ====== K: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF ALGO: TDES M: 01 04 11 22 33 44 55 66 K': DA 21 B8 2D 70 FD F5 C8 DF 2E DD 82 07 E8 49 3F ==================================== Diversified key: DA 21 B8 2D 70 FD F5 C8 DF 2E DD 82 07 E8 49 3F |
AES
En AES, le fonctionnement est là encore similaire.
1 |
Kd = Eaes(Km, ((KeyNo || ID || KeyNo || ID ) xor Km)) |
Ou:
- Kd = Clef diversifiée
- Km = Clef d’origine
- KeyNo = Index de la clef
- ID = Identifiant de la PICC
- Eaes = Méthode de chiffrement AES
- xor = Méthode “Ou Exclusif”
- || = Méthode de concaténation
Vous pouvez expérimenter cette diversification avec le projet GitHub et les arguments :
1 2 3 4 5 6 7 8 |
mvn exec:java -Dstandard=AN0148_AES -Duid=04112233445566 -Dkey=00112233445566778899AABBCCDDEEFF -DkeyIndex=1 ====== AN0148 DIVERSIFICATION ====== K: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF ALGO: AES M: 01 04 11 22 33 44 55 66 01 04 11 22 33 44 55 66 K': B9 B6 1B 27 99 75 03 C8 C5 20 3E ED 28 1D 8C 0B ==================================== Diversified key: B9 B6 1B 27 99 75 03 C8 C5 20 3E ED 28 1D 8C 0B |
Standard AN10922
Le standard AN10922 est plus récent et détaillé dans le document “NIST-SP-800-38B”.
Il est réalisé en AES (128 ou 192) ou en TDEA (avec des clefs de 16 et 24 octets). A la place de la méthode “xor” utilisée en AN0148, c’est la méthode CMAC (réputée plus fiable) qui est utilisée.
Les données utilisées pour diversifier les clefs sont l’ID de la PICC, l’ID de l’application (3 octets), une graine choisie lors de la configuration de l’algorithme.
La méthode “cmac” est détaillée dans le document “NIST-SP-800-38B” et implémentée dans le projet mis à disposition sur GitHub.
AES (128 bits)
1 2 3 4 |
DIV = (01h || ID || AID || SEED) Padded = length(DIV) == 32 D = pad32(DIV) Kd = CMACaes128(K, D, Padded) |
Ou:
- Kd = Clef diversifiée
- K = Clef d’origine
- ID = Identifiant de la PICC
- CMACaes128 = Méthode “CMAC” avec l’algorithme AES 128 bits
- || = Méthode de concaténation
- SEED = Graine de diversification
- length = Méthode d’obtention de la taille d’une variable
- pad32 = Méthode permettant de compléter une variable pour que sa taille soit égale à 32 octets.
Vous pouvez expérimenter cette diversification avec le projet GitHub et les arguments :
1 2 3 4 5 6 7 8 9 10 |
mvn exec:java -Dstandard=AN10922_AES128 -Duid=04112233445566 -Daid=F5865D -Dkey=00112233445566778899AABBCCDDEEFF -DsystemIdentifier=010203040506070809 ===== AN10922 DIVERSIFICATION ====== K: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF K0: FD E4 FB AE 4A 09 E0 20 EF F7 22 96 9F 83 83 2B K1: FB C9 F7 5C 94 13 C0 41 DF EE 45 2D 3F 07 06 D1 K2: F7 93 EE B9 28 27 80 83 BF DC 8A 5A 7E 0E 0D 25 M: 01 04 11 22 33 44 55 66 5D 86 F5 01 02 03 04 05 06 07 08 09 K': 37 13 1F 0F 6B EF 7B 93 2A 6E 8B 25 AE 04 9C 36 ==================================== Diversified key: 37 13 1F 0F 6B EF 7B 93 2A 6E 8B 25 AE 04 9C 36 |
AES (192 bits)
Le procédé est identique à la version “AES 128 mais il est répété deux fois avec une constante différente afin de générer deux clefs diversifiées.
1 2 3 4 5 6 7 8 9 |
DIV1 = (11h || ID || AID || SEED) Padded1 = length(DIV1) == 32 D1 = pad32(DIV1) KdA = CMACaes192(K, D1, Padded1) DIV2 = (12h || ID || AID || SEED) Padded2 = length(DIV2) == 32 D2 = pad32(DIV2) KdB = CMACaes192(K, D2, Padded2) Kd = KdA0-7 || (KdA8-15 xor KdB0-7 ) || KdB8-15 |
Ou:
- Kd = Clef diversifiée
- K = Clef d’origine
- ID = Identifiant de la PICC
- CMACaes192 = Méthode “CMAC” avec l’algorithme AES 192 bits
- || = Méthode de concaténation
- SEED = Graine de diversification
- length = Méthode d’obtention de la taille d’une variable
- pad32 = Méthode permettant de compléter une variable pour que sa taille soit égale à 32 octets.
- xor = Méthode “Ou Exclusif”
Vous pouvez expérimenter cette diversification avec le projet GitHub et les arguments :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
mvn exec:java -Dstandard=AN10922_AES192 -Duid=04112233445566 -Daid=F5865D -Dkey=00112233445566778899AABBCCDDEEFF0102030405060708 -DsystemIdentifier=010203040506070809 ===== AN10922 DIVERSIFICATION ====== ALGO: AES K: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 01 02 03 04 05 06 07 08 --- D1 --- K0: 52 DB 5A FE 7B 64 EF FA B1 E9 2E EA 98 3C 5F 73 K1: A5 B6 B5 FC F6 C9 DF F5 63 D2 5D D5 30 78 BE E6 K2: 4B 6D 6B F9 ED 93 BF EA C7 A4 BB AA 60 F1 7D 4B M: 11 04 11 22 33 44 55 66 5D 86 F5 01 02 03 04 05 06 07 08 09 Ka': B8 3B 4B 13 02 E2 23 D5 D9 ED 58 E5 53 36 B9 70 --- D2 --- K0: 52 DB 5A FE 7B 64 EF FA B1 E9 2E EA 98 3C 5F 73 K1: A5 B6 B5 FC F6 C9 DF F5 63 D2 5D D5 30 78 BE E6 K2: 4B 6D 6B F9 ED 93 BF EA C7 A4 BB AA 60 F1 7D 4B M: 12 04 11 22 33 44 55 66 5D 86 F5 01 02 03 04 05 06 07 08 09 Kb': 06 85 F6 C5 B4 79 C1 50 E4 94 B5 E9 4C 2A 6F C0 ---------- K': B8 3B 4B 13 02 E2 23 D5 DF 68 AE 20 E7 4F 78 20 E4 94 B5 E9 4C 2A 6F C0 ==================================== Diversified key: B8 3B 4B 13 02 E2 23 D5 DF 68 AE 20 E7 4F 78 20 E4 94 B5 E9 4C 2A 6F C0 |
Pour finir
L’utilisation de la diversification des clefs symétriques devrait être systématisée. Les processus cryptographiques sont standardisés, documentés et simple à implémenter.
Les standards les plus récents datent de 2010, les processeurs actuels sont largement capables de mener une diversification sans perte significative de temps.
A ce jour il existe cependant deux limitations :
- Les lecteurs qui n’implémenteraient pas cette fonctionnalité.
- L’utilisation d’ID aléatoire. C’est le cas sur tous les Smartphones ou presque.
Il faudra donc veiller à ce qu’un identifiant unique et fixe soit fourni par les récepteurs en “Random ID” et maîtriser la population des lecteurs afin de s’assurer qu’ils sont tous en capacité de réaliser la diversification.
A noter que l’on n’est pas obligé de diversifier l’intégralité des clefs utilisées, on peut le faire uniquement sur certaines clefs critiques.
Enfin, privilégier l’utilisation de l’AES au lieu du DES/3DES, beaucoup plus rapide et sécurisé.