2008-12-11 5 views
10

Es scheint, dass es sind 6 Variationen auf CBC-MAC-Algorithmus. Ich habe versucht, den MAC-Algorithmus auf dem PINPad 1000SE zu entsprechen [welches Handbuch ist ISO 9797-1 Algorithmus 1].ISO 9797-1 Algorithmus 1 [CBC-MAC] in C#

bekam ich einen guten Start von here.

Und ich codiert den Algorithmus wie folgt:

public static byte[] CalculateMAC(this IPinPad pinpad, byte[] message, byte[] key) 
{ 
    //Divide the key with Key1[ first 64 bits] and key2 [last 64 bits] 
    var key1 = new byte[8]; 
    Array.Copy(key, 0, key1, 0, 8); 

    var key2 = new byte[8]; 
    Array.Copy(key, 8, key2, 0, 8); //64 bits 

    //divide the message into 8 bytes blocks 
    //pad the last block with "80" and "00","00","00" until it reaches 8 bytes 
    //if the message already can be divided by 8, then add 
    //another block "80 00 00 00 00 00 00 00" 
    Action<byte[], int> prepArray = (bArr, offset) => 
            { 
             bArr[offset] = 0; //80 
             for (var i = offset + 1; i < bArr.Length; i++) 
              bArr[i] = 0; 
            }; 
    var length = message.Length; 
    var mod = length > 8? length % 8: length - 8; 

    var newLength = length + ((mod < 0) ? -mod : (mod > 0) ? 8 - mod : 0); 
    //var newLength = length + ((mod < 0) ? -mod : (mod > 0) ? 8 - mod : 8); 
    Debug.Assert(newLength % 8 == 0); 

    var arr = new byte[newLength]; 
    Array.Copy(message, 0, arr, 0, length); 
    //Encoding.ASCII.GetBytes(message, 0, length, arr, 0); 
    prepArray(arr, length); 
    //use initial vector {0,0,0,0,0,0,0,0} 
    var vector = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; 

    //encrypt by DES CBC algorith with the first key KEY 1 
    var des = new DESCryptoServiceProvider { Mode = CipherMode.CBC }; 
    var cryptor = des.CreateEncryptor(key1, vector); 
    var outputBuffer = new byte[arr.Length]; 
    cryptor.TransformBlock(arr, 0, arr.Length, outputBuffer, 0); 

    //Decrypt the result by DES ECB with the second key KEY2 [Original suggestion] 
    //Now I'm Encrypting 
    var decOutputBuffer = new byte[outputBuffer.Length]; 
    des.Mode = CipherMode.ECB; 
    var decryptor = des.CreateEncryptor(key2, vector); 
    //var decryptor = des.CreateDecryptor(key2, vector); 
    decryptor.TransformBlock(outputBuffer, 0, outputBuffer.Length, decOutputBuffer, 0); 

    //Encrypt the result by DES ECB with the first key KEY1 
    var finalOutputBuffer = new byte[decOutputBuffer.Length]; 
    var cryptor2 = des.CreateEncryptor(key1, vector); 
    cryptor2.TransformBlock(decOutputBuffer, 0, decOutputBuffer.Length, finalOutputBuffer, 0); 

    //take the first 4 bytes as the MAC 
    var rval = new byte[4]; 
    Array.Copy(finalOutputBuffer, 0, rval, 0, 4); 
    return rval; 
} 

Dann entdeckte ich, es sind 3 Padding-Verfahren und derjenige, der mir einen Start gab müssen nicht unbedingt richtig sein. Das Handbuch kam mir wieder zu Hilfe. Es scheint, das Gerät puffert nur mit 0s. Zusätzlicher Block wird auch nirgends erwähnt, so habe ich die folgenden Änderungen:

Action<byte[], int> prepArray = (bArr, offset) => 
            { 
             bArr[offset] = 0; ... } 

Keinen zusätzlichen Block (falls mod 0 [teilbar durch 8] nicht Arraylänge ändern)

var newLength = length + ((mod < 0) ? -mod : (mod > 0) ? 8 - mod : 0); 

Der ursprüngliche Vorschlag wollte mich im zweiten Schritt zu entschlüsseln ... aber Valery here schlägt vor, dass es den ganzen Weg verschlüsseln. Also habe ich Decrypt zu Encrypt geändert. Aber ich bin immer noch nicht in der Lage, die erforderlichen MAC ...

Handbuch sagt für Schlüssel "6AC292FAA1315B4D8234B3A3D7D5933A" [da der Schlüssel 16 Bytes sein sollte, dachte ich, der Schlüssel hier ist hex Zeichenfolge, so nahm ich Byte-Werte von 6A, C2 , 92, ... FA new byte [] {106, 194, 146, ...] die MAC 7B sein sollte, 40, BA, 95 [4 Byte], wenn die Meldung [0x1A + ​​Byte-Array von MENTERODOMETER ist]

Kann jemand helfen? Bitte?


Da Pinpad erfordert, dass das erste Zeichen in-Nachricht ist eine 0x1a ...

public static byte[] CalculateAugmentedMAC(this IPinPad pinpad, string message, byte[] key) 
{ 
    var arr = new byte[message.Length + 1]; 
    var source = Encoding.ASCII.GetBytes(message); 
    arr[0] = 0x1a; //ClearScreenIndicator 
    Array.Copy(source, 0, arr, 1, source.Length); 
    return CalculateMAC(pinpad, arr, key); 
} 

ich den Code oben mit diesem Eingang Aufruf:

var result = pad.CalculateAugmentedMAC("MENTERODOMETER", new byte[] { 106, 194, 146, 250, 161, 49, 91, 77, 130, 52, 179, 163, 215, 213, 147, 58 }); 
+2

Neugierig. Warum sollten Sie sich an der Entschlüsselung von PINPad-Daten beteiligen? Der PINPad-Workflow wurde entwickelt, um verschlüsselte Daten direkt an die Bank des Händlers zu senden. Hierfür werden die DUKPT-Schlüssel verwendet, die von der Bank generiert und vom PINPad-Anbieter im PINPad installiert werden. Sogar bis zu dem Punkt, an dem wir Software zum direkten Steuern der verschiedenen Benutzeroberflächen und anderer Verhaltensweisen von PINPads geschrieben haben, konnten und mussten wir den verschlüsselten PIN-Datenumschlag, der als Teil des Prozesses bereitgestellt wurde, niemals verschlüsseln. – Bill

+0

Bill, du hast recht ... Aber wenn du eine Loyalitätsmanagement-Anwendung schreiben würdest, die den Benutzern eine PIN ermöglicht, musst du sie ohne diese vorprogrammierten Schlüssel verwenden .... PINPad 1000SEs früheres Modell - kann mich nicht erinnern oben auf meinem Kopf - erlaubte Ihnen, eine PIN zu erhalten und das als Klartext zu senden. Die späteren Modelle verschlüsseln die PIN und wir können nicht darauf kommen ... –

Antwort

2

meisten CBC-MAC Algorithmen sind in BouncyCastle JCE Provider implementiert.

Blick auf: BouncyCastleProvider.java

sind Sie wahrscheinlich für DESEDEISO9797ALG1MACWITHISO7816-4PADDING suchen, das ist ein Alias ​​für DESEDEMAC64WITHISO7816-4PADDING, implementiert hier (na ja, es ist eine spezifische Konfiguration von CBCBlockCipherMac mit dem DESedeEngine und ISO7816d4Padding, werden Sie springen müssen zwischen einigen Klassen das ganze Bild zu bekommen): JCEMac.java

auch einen Blick auf JPOs:

JCESecurityModule.java

und ihre beigetragen Einzelhandel MAC-Algorithmus Implementierung:

retail-mac-contributed-by-vsalaman.zip

0

Ich bin ziemlich sicher, dass (IIRC), die Sie TransformFinalBlock am Ende (pro Verschlüssler) anrufen müssen.

0

kann nicht auf Ihre speziellen Terminal beantworten, aber ich benutze diese zu Test MACs.

public static byte[] GenerateMAC(byte[] key, byte[] data) 
{ 
    using (MACTripleDES mac = new MACTripleDES(key)) 
     return mac.ComputeHash(data); 
}