ID TECH
Contact
Tous les articles techniques

Article technique

Comment déchiffrer les données de carte de crédit, partie II

Les clients nous posent souvent la question suivante : Comment déchiffrer les données provenant de mon lecteur de carte de crédit ID TECH ?

La réponse : vous devez connaître l'algorithme utilisé pour chiffrer les données, ainsi que la clé employée. Vous pourrez alors déchiffrer les données à l'aide de cette clé.

De nos jours, la quasi-totalité des données de cartes de crédit est chiffrée à l'aide d'une clé à usage unique, obtenue via un mécanisme spécial de gestion des clés appelé DUKPT (soit Derived Unique Key Per Transaction, ou « clé unique dérivée par transaction »). Il est essentiel de comprendre que dans l'univers DUKPT, chaque transaction dispose de sa propre clé. Cette clé ne peut être réutilisée pour aucune autre transaction ; les attaques par rejeu sont donc impossibles.

La question est la suivante : comment dériver une clé DUKPT permettant de déverrouiller une transaction donnée ? En règle générale, il vous faut le numéro de série de clé (KSN) associé à la transaction, ainsi qu'une valeur spéciale appelée IPEK (Initial PIN Encryption Key), c'est-à-dire la clé initiale injectée dans le lecteur de carte de crédit. L'IPEK est elle-même dérivée d'une clé ultraconfidentielle — qui n'est jamais injectée dans un lecteur de carte — appelée BDK (Base Derivation Key). Contrairement à la BDK, l'IPEK est propre à un appareil physique donné. (Une seule BDK peut être à l'origine de nombreuses IPEK uniques.) Si vous ne connaissez pas l'IPEK de votre appareil — ce qui est tout à fait normal, car l'IPEK n'est jamais consignée nulle part —, vous pouvez la dériver à partir d'un KSN et d'une Base Derivation Key, en appliquant la méthode décrite dans la Partie I de cet article.

La dérivation d'une clé de session (parfois appelée clé de travail, ou simplement « clé de données ») se conçoit mieux comme un processus en 3 étapes, à savoir :

1. Utiliser la BDK et le KSN pour dériver l'IPEK. (Voir la Partie I de cet article pour plus de détails sur la procédure à suivre.)

2. Utiliser l'algorithme de dérivation de clé ANSI X9.24 (DUKPT) pour dériver une clé de base, ou « clé dérivée » initiale, à partir du KSN et de l'IPEK.

3. Convertir la clé dérivée obtenue à l'étape 2 en Data Key, PIN Key ou MAC Key, selon votre choix. (À noter que, si la plupart des lecteurs de cartes de crédit sont configurés pour utiliser la variante Data comme clé de session de transaction, certains utilisent en réalité la variante PIN à la place.)

Voyons maintenant ce qu'implique l'obtention de la « clé dérivée » (étape 2), qui constitue de loin la partie la plus laborieuse du processus en trois étapes. Une fois la clé dérivée obtenue, nous verrons comment la transformer en variante Data, PIN ou MAC, ce qui est relativement simple.

Nous aurons recours à du pseudocode dans les sections suivantes, mais soyez assurés que vous trouverez un code source complet et fonctionnel (en JavaScript) pour toutes les étapes ci-dessous dans notre populaire Outil de chiffrement/déchiffrement. (Essayez-le dès maintenant si vous ne l'avez pas encore fait. Il s'agit d'une page web autonome qui fonctionne dans tout navigateur moderne.)

Dérivation d'une clé

Pour dériver la clé de base à partir de laquelle une variante Data, PIN ou MAC peut être créée, vous devez disposer d'un KSN de transaction et d'un IPEK. Une fois ces éléments en main (voir à nouveau : La première partie de cette série), procédez comme suit :

1. Extraire les 8 octets inférieurs (les plus à droite) de votre KSN de 10 octets. Ignorer les deux octets supérieurs.

2. Créer une variable BaseKSN destinée à contenir une version masquée de votre KSN sur 8 octets. Obtenir cette version masquée en appliquant un ET logique (AND) entre le KSN sur 8 octets de l'étape 1 et la valeur (hexadécimale) 0xFFFFFFFFFFE00000.

3. Extraire les bits de compteur de votre KSN original sur 10 octets (non masqué !) en appliquant un ET logique (AND) entre ses trois octets inférieurs et la valeur 0x1FFFFF. (Rappel : les 21 bits inférieurs d'un KSN constituent le compteur de transaction.) Nous stockerons cette valeur dans une variable appelée (sans surprise) counter.

4. Copiez votre IPEK de 16 octets dans une variable appelée curKey.

5. Nous devons maintenant mettre en place une boucle. À chaque itération, nous allons examiner les bits du compteur (en commençant par le bit de poids fort, soit le 21e bit ; au deuxième passage, nous vérifierons le 20e bit, puis le 19e, et ainsi de suite). Chaque fois que nous trouvons un bit activé, nous l'appliquons par OR dans le BaseKSN, puis nous appelons generateKey() pour mettre à jour curKey. Le BaseKSN accumule des bits à chaque passage dans la boucle, et la valeur curKey se met à jour à chaque bit du compteur activé trouvé.

Que fait generateKey() ? Bonne question ! Si votre langage de programmation prend en charge les grands entiers (BigInteger), le code ressemblera à quelque chose comme ceci :

Bien. Vous pouvez constater que la clé de 16 octets est masquée, puis utilisée pour chiffrer la valeur ksn de 8 octets, afin d'obtenir la moitié gauche (les 8 octets de gauche) d'une nouvelle clé. La moitié droite de la nouvelle clé est un chiffrement obtenu à partir du même ksn, mais en utilisant une clé non masquée.

Enfin, vous devez savoir ce que fait encryptRegister() ressemble à ceci :

Notez que le Cipher Block Chaining est en réalité sans signification ici, car nous chiffrons une valeur de 8 octets (un seul bloc de données). Il n'y a rien à « chaîner ». Il est inclus dans le code uniquement parce que la routine de chiffrement requiert un paramètre indiquant si le chaînage est activé ou non.

Notez également que nous utilisons une clé de 8 octets pour effectuer le chiffrement. TDES bascule par défaut vers un DES simple lorsque la clé ne fait que 8 octets. En effet, avec le triple DES, une clé de 8 octets produirait un cycle chiffrement/déchiffrement/chiffrement équivalent à un simple chiffrement.

En termes simples, la routine utilise les 8 premiers octets d'une clé de 16 octets pour chiffrer une valeur spéciale obtenue par un XOR entre les 8 derniers octets de la clé et le ksn (de 8 octets). Le résultat est un hachage unidirectionnel du ksn.

En assemblant l'ensemble, la boucle de l'étape 5 ci-dessus produit une valeur curKey qui constitue une clé de base à partir de laquelle nous pouvons dériver des variantes Data, PIN ou MAC. (La boucle de l'étape 5 fait partie, ou devrait faire partie, d'une fonction qui retourne au final curKey, laquelle représente la clé de base.)

Il est maintenant temps d'examiner plus en détail ces trois options de « variantes de clé ».

Création des variantes de clé Data, PIN et MAC

La norme ANSI X9.24 permet à une clé DUKPT d'adopter l'une des trois formes finales, appelées variantes. Ces formes sont MAC, PIN et Data. Nous reportons à plus tard toute discussion sur l'utilisation de ces différents types de clés afin de nous concentrer sur leur mode de création.

Le point de départ de chacune des variantes est une clé de base DUKPT (la clé dérivée que nous avons désignée par curKey à l'étape 5 plus haut). Pour obtenir la variante MAC, il suffit d'effectuer un XOR entre la clé de base (la « clé dérivée ») et une constante spéciale :

La variante PIN est créée de manière similaire, mais en utilisant une constante différente :

La variante Data nécessite quant à elle une autre constante :

Pour les variantes MAC et PIN, l'opération XOR constitue l'étape finale de la création de la clé de session correspondante. Pour la variante Data, il est d'usage d'effectuer une étape supplémentaire, faisant intervenir un hachage unidirectionnel (afin d'exclure toute possibilité de rétro-transformation d'une clé Data en clé MAC). En pseudocode :

En clair : commencez par obtenir une version 24 octets de votre clé dérivée en appliquant la méthode d'expansion EDE3. (Cela consiste simplement à copier les 8 premiers octets d'une clé de 16 octets à la fin de celle-ci, créant ainsi une clé de 24 octets dont les 8 premiers et les 8 derniers octets sont identiques.) Utilisez cette clé pour chiffrer en TDES les 8 premiers octets de votre clé dérivée de 16 octets, obtenant ainsi un bloc chiffré de 8 octets. Il s'agit de la moitié gauche de la clé de données finale. Pour créer la moitié droite, utilisez la même clé de 24 octets pour chiffrer les 8 derniers octets de la clé dérivée. Combinez les deux blocs chiffrés de 8 octets (parties gauche et droite) et l'opération est terminée.

Valeurs de référence connues

Si vous souhaitez reproduire cette procédure par vous-même, vous pouvez vérifier vos résultats en les comparant à des valeurs de référence connues. Commencez avec un BDK de 16 octets dont la valeur est 0123456789ABCDEFFEDCBA9876543210 (en hexadécimal), qui est la clé de test communément utilisée. Utilisez ensuite la valeur de test KSN 629949012C0000000003. Ces deux valeurs doivent vous permettre de dériver un IPEK égal à D2943CCF80F42E88E23C12D1162FD547. (Consultez la Partie I de cet article pour savoir comment dériver l'IPEK.)

En partant de l'IPEK mentionné précédemment, vous devriez obtenir les valeurs suivantes lors de la dérivation d'une « clé dérivée » (ou clé de base DUKPT) :

Lors du premier passage dans le « if » de la boucle du compteur KSN, votre BaseKSN sera égal à 49012C0000000002 et curKey deviendra B58CDA5C7A1E9FF5E7335B988626D01A après generateKey().

Au second passage dans le « if » de la boucle du compteur, vous aurez traité les deux bits « ON » du compteur ; votre BaseKSN sera donc 49012C0000000003 et la curKey résultante sera 841AB7B94ED086EBC2B8A8385DA7DFCA. (N'oubliez pas que vous effectuez un OR des bits du compteur, MSB en premier, dans le BaseKSN. Si le compteur se termine par 0x0F, le BaseKSN passera successivement de 49012C0000000008 à 49012C000000000C, puis à 49012C000000000E, et enfin à 49012C000000000F au fur et à mesure des opérations OR.)

Votre « clé dérivée » sera donc 841AB7B94ED086EBC2B8A8385DA7DFCA.

Après application du XOR avec la constante de variante de données, la clé dérivée deviendra 841AB7B94E2F86EBC2B8A8385D58DFCA.

Après chiffrement des moitiés supérieure et inférieure de cette valeur, à l'aide d'une clé d'expansion EDE3 de 841AB7B94E2F86EBC2B8A8385D58DFCA841AB7B94E2F86EB, vous devriez obtenir une clé de données finale de F739AEF595D3877F731782D28BB6AC4F. Autrement dit : en utilisant la clé EDE3 de 24 octets pour chiffrer 841AB7B94E2F86EB, vous devriez obtenir un chiffré de F739AEF595D3877F, et en utilisant la même clé pour chiffrer C2B8A8385D58DFCA, vous devriez obtenir un chiffré de 731782D28BB6AC4F. Concaténez les deux chiffrés, et le tour est joué. Vous disposez désormais d'une clé de 16 octets permettant de déchiffrer les données issues de la transaction dont le KSN était 629949012C0000000003.

Exemple de code : l'outil de chiffrement/déchiffrement ID TECH

Pour consulter le code source complet de toutes les routines de dérivation de clé DUKPT présentées ici, téléchargez (et examinez le code source de) notre outil basé sur HTML et JavaScript Outil de chiffrement/déchiffrement, qui permet de calculer des IPEK, de dériver les 3 variantes de clé DUKPT, de chiffrer ou déchiffrer des données via TDES ou AES, et bien plus encore. Vous pouvez utiliser l'excellente console développeur de Chrome pour parcourir le code de l'outil en temps réel, inspecter les valeurs des variables au fil de leurs modifications, définir des points d'arrêt, etc. C'est un formidable outil d'apprentissage — et il est gratuit ! Téléchargez donc Outil de chiffrement/déchiffrement, explorez-le, et parlez-en autour de vous. À ma connaissance, il s'agit de la seule implémentation DUKPT en JavaScript pur disponible sur le Web.