Technischer Beitrag
Kreditkartendaten entschlüsseln, Teil II
Kunden fragen häufig: Wie kann ich die Daten entschlüsseln, die mein ID TECH Kreditkartenlesegerät ausgibt?
Die Antwort: Sie müssen den Algorithmus kennen, der zur Verschlüsselung der Daten verwendet wurde, sowie den dabei eingesetzten Schlüssel. Anschließend können Sie die Daten mit diesem Schlüssel entschlüsseln.
Heutzutage werden nahezu alle Kreditkartendaten mit einem Einmalschlüssel verschlüsselt, der über ein spezielles Schlüsselverwaltungsverfahren namens DUKPT (Derived Unique Key Per Transaction) erzeugt wird. Es ist wichtig zu verstehen, dass im DUKPT-Verfahren jede Transaktion ihren eigenen Schlüssel erhält. Dieser Schlüssel kann für keine weitere Transaktion wiederverwendet werden – Replay-Angriffe sind daher ausgeschlossen.
Die entscheidende Frage lautet: Wie lässt sich ein DUKPT-Schlüssel ableiten, der eine bestimmte Transaktion entschlüsselt? Die Antwort: Im Wesentlichen benötigen Sie die Key Serial Number (KSN) der Transaktion sowie einen speziellen Wert namens IPEK – den Initialschlüssel, der in das Kreditkartenlesegerät eingespielt wurde. Der IPEK seinerseits wird aus einem streng geheimen Schlüssel abgeleitet, der niemals in ein Lesegerät eingespielt wird: dem BDK (Base Derivation Key). Im Gegensatz zum BDK ist der IPEK eindeutig einem bestimmten physischen Gerät zugeordnet. (Ein einziger BDK kann Grundlage vieler einzigartiger IPEKs sein.) Falls Sie den IPEK Ihres Geräts nicht kennen – was zu erwarten ist, da der IPEK nirgendwo schriftlich festgehalten wird –, können Sie ihn mithilfe einer KSN und eines Base Derivation Key nach dem in Teil I dieses Artikels.
Die Ableitung eines Sitzungsschlüssels (mitunter auch als Working Key oder schlicht „Data Key" bezeichnet) lässt sich am besten als dreistufigen Prozess verstehen. Die Schritte sind:
1. BDK und KSN verwenden, um den IPEK abzuleiten. (Siehe Teil I dieses Artikels für Details zur Vorgehensweise.)
2. Verwenden Sie den ANSI X9.24 (DUKPT)-Schlüsselableitungsalgorithmus, um aus dem KSN und dem IPEK einen Basisschlüssel oder initialen „abgeleiteten Schlüssel" zu erzeugen.
3. Wandeln Sie den in Schritt 2 abgeleiteten Schlüssel in einen Data Key, PIN Key oder MAC Key Ihrer Wahl um. (Beachten Sie, dass die meisten Kreditkartenlesegeräte zwar so konfiguriert sind, dass sie die Data-Variante des Schlüssels als Transaktionssitzungsschlüssel verwenden, einige jedoch tatsächlich die PIN-Variante nutzen.)
Schauen wir uns an, was die Ermittlung des „abgeleiteten Schlüssels" (Schritt 2) beinhaltet, da dies bei weitem der aufwändigste Teil des dreistufigen Prozesses ist. Sobald wir den abgeleiteten Schlüssel haben, erläutern wir, wie er in eine Data-, PIN- oder MAC-Variante umgewandelt werden kann – was vergleichsweise einfach ist.
Im Folgenden wird eine Reihe von Pseudocode-Beispielen verwendet. Vollständigen, funktionsfähigen Quellcode (in JavaScript) für alle nachfolgenden Schritte finden Sie jedoch in unserem beliebten Encrypt/Decrypt Tool. (Probieren Sie es jetzt aus, falls Sie es noch nicht getan haben. Es handelt sich um eine eigenständige Webseite, die in jedem modernen Browser funktioniert.)
Schlüsselableitung
Um den Basisschlüssel abzuleiten, aus dem eine Data-, PIN- oder MAC-Variante erstellt werden kann, benötigen Sie einen Transaktions-KSN und einen IPEK. Sobald Sie diese haben (nochmals: siehe Teil I dieser Serie), gehen Sie wie folgt vor:
1. Nehmen Sie die unteren (rechtsseitigen) 8 Bytes Ihres 10-Byte-KSN. Die oberen zwei Bytes werden verworfen.
2. Erstellen Sie eine Variable BaseKSN, um eine maskierte Version Ihres 8-Byte-KSN zu speichern. Erzeugen Sie die maskierte Version, indem Sie den 8-Byte-KSN aus Schritt 1 mit dem (hexadezimalen) Wert 0xFFFFFFFFFFE00000 AND-verknüpfen.
3. Ermitteln Sie die Zählerbits aus Ihrer ursprünglichen (nicht maskierten!) 10-Byte-KSN, indem Sie deren unterste drei Bytes mit 0x1FFFFF verUNDen. (Zur Erinnerung: Die untersten 21 Bits einer KSN bilden den Transaktionszähler.) Diesen Wert speichern wir in einer Variablen namens (wie könnte es anders sein?) counter.
4. Kopieren Sie Ihren 16-Byte-IPEK in eine Variable namens curKey.
5. Nun müssen wir eine Schleife einrichten. In jedem Schleifendurchlauf prüfen wir die Zählerbits (beginnend mit dem höchsten Bit, also dem 21. Bit; im zweiten Durchlauf prüfen wir das 20. Bit; dann das 19. Bit; und so weiter). Jedes Mal, wenn wir ein gesetztes Bit finden, verODERn wir es in die BaseKSN und rufen anschließend generateKey() auf, um curKeyzu aktualisieren. Die BaseKSN akkumuliert mit jedem Schleifendurchlauf Bits, und der Wert von curKey wird mit jedem gefundenen gesetzten Zählerbit aktualisiert.
Was macht generateKey() ? Gute Frage! Falls Ihre Programmiersprache BigInteger-Arithmetik unterstützt, sieht der Code in etwa so aus:
Gut. Sie sehen, dass der 16-Byte-Schlüssel maskiert und anschließend zur Verschlüsselung der 8-Byte- ksn Wert, um die linke Hälfte (die linken 8 Bytes) eines neuen Schlüssels zu erhalten. Die rechte Hälfte des neuen Schlüssels ist eine Verschlüsselung, die aus demselben ksn erstellt wird, jedoch unter Verwendung eines unmaskierten Schlüssels.
Abschließend müssen Sie wissen, wie encryptRegister() aussieht. Hier ist es:
Beachten Sie, dass Cipher Block Chaining hier eigentlich keine Bedeutung hat, da wir einen 8-Byte-Wert (einen Datenblock) verschlüsseln. Es gibt nichts zu „verketten". Es ist im Code lediglich enthalten, weil die Verschlüsselungsroutine zufällig einen Parameter erfordert, der angibt, ob Chaining verwendet werden soll oder nicht.
Beachten Sie außerdem, dass wir für die Verschlüsselung einen 8-Byte-Schlüssel verwenden. TDES fällt auf einfaches DES zurück, wenn der Schlüssel nur 8 Bytes lang ist. Das liegt daran, dass ein 8-Byte-Schlüssel bei Triple DES einen Encrypt/Decrypt/Encrypt-Zyklus ergibt, der einer einfachen Verschlüsselung entspricht.
Die vereinfachte Erklärung des Vorgangs lautet: Die Routine verwendet die oberen 8 Bytes eines 16-Byte-Schlüssels, um einen speziellen Wert zu verschlüsseln, der durch XOR-Verknüpfung der unteren 8 Bytes des Schlüssels mit dem (8-Byte-) ksn entsteht. Das Ergebnis ist ein Einweg-Hash des ksn.
Alles zusammengenommen ergibt sich, dass die Schleife aus Schritt 5 oben einen curKey Wert erzeugt, der als Basisschlüssel dient, aus dem wir Varianten für Daten, PIN oder MAC ableiten können. (Die Schleife in Schritt 5 ist oder sollte Teil einer Funktion sein, die am Ende curKey zurückgibt, welcher der Basisschlüssel ist.)
Es ist nun an der Zeit, diese drei „Schlüsselvarianten"-Optionen genauer zu betrachten.
Erstellen von Daten-, PIN- und MAC-Schlüsselvarianten
ANSI X9.24 erlaubt es, dass ein DUKPT-Schlüssel eine von drei endgültigen Formen annimmt, die als Varianten bezeichnet werden. Diese Formen sind MAC, PIN und Daten. Lassen Sie uns zunächst auf eine Erörterung verzichten, wofür diese verschiedenen Schlüsseltypen verwendet werden, und uns stattdessen darauf konzentrieren, wie sie erstellt werden.
Der Ausgangspunkt für jede der Varianten ist ein DUKPT-Basisschlüssel (der abgeleitete Schlüssel, den wir curKey in Schritt 5 weiter oben genannt haben). Um die MAC-Variante zu erhalten, müssen Sie lediglich den Basisschlüssel (den „abgeleiteten Schlüssel") mit einer speziellen Konstante per XOR verknüpfen:
Die PIN-Variante wird auf ähnliche Weise erzeugt, jedoch mit einer anderen Konstante:
Die Data-Variante erfordert wiederum eine andere Konstante:
Bei MAC- und PIN-Varianten stellt die XOR-Operation den abschließenden Schritt bei der Erstellung des jeweiligen Sitzungsschlüssels dar. Bei der Data-Variante ist es üblich, einen zusätzlichen Schritt durchzuführen, der einen Einweghashalgorithmus beinhaltet (um jede Möglichkeit auszuschließen, einen Data-Schlüssel in einen MAC-Schlüssel zurückzutransformieren). In Pseudocode:
Auf Deutsch: Ermitteln Sie zunächst eine 24-Byte-Version Ihres abgeleiteten Schlüssels mithilfe der EDE3-Erweiterungsmethode. (Dies bedeutet schlicht, die ersten 8 Bytes eines 16-Byte-Schlüssels an dessen Ende anzufügen und so einen 24-Byte-Schlüssel zu erzeugen, bei dem die ersten und letzten 8 Bytes identisch sind.) Verwenden Sie diesen Schlüssel, um die ersten 8 Bytes Ihres 16-Byte-Ursprungsschlüssels per TDES zu verschlüsseln und dadurch einen 8-Byte-Chiffretext zu erzeugen. Das ist die linke Hälfte des späteren Data-Schlüssels. Um die rechte Hälfte zu erstellen, verwenden Sie denselben 24-Byte-Schlüssel, um die unteren 8 Bytes des abgeleiteten Schlüssels zu verschlüsseln. Fügen Sie die beiden 8-Byte-Chiffretexte (linkes und rechtes Teilstück) zusammen, und Sie sind fertig.
Bekannte Referenzwerte
Wenn Sie dies selbst nachvollziehen möchten, empfiehlt es sich, Ihre Ergebnisse mit bekannten Referenzwerten zu vergleichen. Beginnen Sie daher mit einem 16-Byte-BDK von 0123456789ABCDEFFEDCBA9876543210 (hexadezimal) – dem Testschlüsselwert, der allgemein verwendet wird. Verwenden Sie als Test-KSN-Wert 629949012C0000000003. Mit diesen beiden Werten sollten Sie einen IPEK von D2943CCF80F42E88E23C12D1162FD547 ableiten können. (Lesen Sie Teil I dieses Artikels , wenn Sie sehen möchten, wie der IPEK abgeleitet wird.)
Ausgehend vom oben genannten IPEK sollten Sie beim Ableiten eines „abgeleiteten Schlüssels" (oder DUKPT-Basisschlüssels) die folgenden Werte erhalten:
Beim ersten Durchlauf durch das „if" der KSN-Zählerschleife ist Ihr BaseKSN wird 49012C0000000002 sein und curKey wird nach dem Vorgang zu B58CDA5C7A1E9FF5E7335B988626D01A generateKey().
Im zweiten Durchlauf durch das „if" der Zählerschleife haben Sie beide „ON"-Bits des Zählers verarbeitet. Daher wird Ihre BaseKSN 49012C0000000003 sein, und der resultierende curKey wird 841AB7B94ED086EBC2B8A8385DA7DFCA sein. (Zur Erinnerung: Die Zählerbits werden per OR-Verknüpfung, beginnend mit dem MSB, in die BaseKSN eingesetzt. Endet der Zähler auf 0x0F, wechselt die BaseKSN sukzessive von 49012C0000000008 über 49012C000000000C und 49012C000000000E zu 49012C000000000F, während die Bits nacheinander per OR verknüpft werden.)
Ihr „abgeleiteter Schlüssel" lautet somit 841AB7B94ED086EBC2B8A8385DA7DFCA.
Nach der XOR-Verknüpfung mit der Datenvarianten-Konstante ändert sich der abgeleitete Schlüssel zu 841AB7B94E2F86EBC2B8A8385D58DFCA.
Nach der Verschlüsselung der oberen und unteren Hälften dieses Werts mit einem EDE3-Erweiterungsschlüssel von 841AB7B94E2F86EBC2B8A8385D58DFCA841AB7B94E2F86EB sollten Sie einen endgültigen Datenschlüssel von F739AEF595D3877F731782D28BB6AC4F erhalten. Das bedeutet: Wenn Sie den 24-Byte-EDE3-Schlüssel verwenden, um 841AB7B94E2F86EB zu verschlüsseln, ergibt sich der Chiffretext F739AEF595D3877F; die Verschlüsselung von C2B8A8385D58DFCA mit demselben Schlüssel ergibt den Chiffretext 731782D28BB6AC4F. Verketten Sie beide Chiffretexte, und Sie sind fertig. Sie verfügen nun über einen 16-Byte-Schlüssel, mit dem Sie die Daten aus der Transaktion entschlüsseln können, deren KSN 629949012C0000000003 war.
Beispielcode: Das ID TECH Encrypt/Decrypt Tool
Den vollständigen Quellcode für alle hier besprochenen DUKPT-Schlüsselableitungsroutinen finden Sie in unserem HTML-und-JavaScript-basierten Tool. Laden Sie es herunter und sehen Sie sich den Quellcode an – Encrypt/Decrypt Tool, das IPEKs berechnen, alle 3 DUKPT-Schlüsselvarianten ableiten, Daten per TDES oder AES ver- und entschlüsseln und vieles mehr kann. Mit den hervorragenden Entwicklertools der Chrome-Konsole können Sie den Code des Tools in Echtzeit schrittweise durchlaufen, Variablenwerte bei Änderungen einsehen, Haltepunkte setzen und vieles mehr. Es ist ein äußerst wertvolles Lernwerkzeug – und kostenlos! Laden Sie das Encrypt/Decrypt Toolherunter, probieren Sie es aus und empfehlen Sie es weiter. Nach meinem Kenntnisstand ist es die einzige reine JavaScript-DUKPT-Implementierung im Web.
