2008-12-11 8 views
10

Wygląda na to, że istnieje 6 odmian algorytmu CBC-MAC. Próbowałem dopasować algorytm MAC do PINPad 1000SE [który zgodnie z instrukcją jest algorytmem ISO 9797-1 1].ISO 9797-1 Algorytm 1 [CBC-MAC] w C#

Mam doskonały początek od here.

I kodowane algorytmem, jak poniżej:

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; 
} 

Wtedy odkryłem tam są 3 programy padding i ten, który dał mi start może niekoniecznie mieć rację. Podręcznik ponownie przyszedł mi na ratunek. Wygląda na to, że urządzenie zawiera tylko pady z 0s. Dodatkowy blok jest również nigdzie nie wspomniano więc zrobiłem poniższe zmiany:

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

Brak dodatkowych bloku (jeśli mod 0 [podzielna przez 8] nie zmieniają długości array)

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

Pierwotna propozycja chciał mnie do odszyfrowania w drugim kroku ... ale Valery here sugeruje, że jest zaszyfrowany do końca. Więc zmieniłem Decrypt na Encrypt. Ale wciąż nie jestem w stanie uzyskać wymaganego adresu MAC ...

Instrukcja mówi o kluczu "6AC292FAA1315B4D8234B3A3D7D5933A" [ponieważ klucz powinien mieć 16 bajtów, domyśliłem się, że klucz jest tutaj ciągiem szesnastkowym, więc wziąłem bajt wartości 6A, C2 , 92, FA ... nowy bajt [] {106, 194, 146, ...] MAC powinien być 7B, 40, BA, 95 [4 bajty], jeśli wiadomość jest [0x1a + tablica bajtów MENTERODOMETER]

Czy ktoś może pomóc? Proszę?


Od pinpad wymaga, że ​​pierwszy znak w wiadomości jest 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); 
} 

Dzwonię powyższy kod z tego wejścia:

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

Ciekawy. Dlaczego warto angażować się w en/deszyfrowanie danych PINPad? Przepływ pracy PINPad przeznaczony jest do wysyłania zaszyfrowanych danych bezpośrednio do banku handlowca za pomocą kluczy DUKPT wygenerowanych przez bank i zainstalowanych w PINPadzie przez dostawcę PINPad. Nawet dotarliśmy do punktu, w którym pisaliśmy oprogramowanie do bezpośredniego kontrolowania różnych interfejsów PINPAD i innych zachowań, nigdy nie byliśmy w stanie, ani nie musieliśmy szyfrować/odszyfrowywać zaszyfrowanej koperty danych PIN dostarczonej w ramach procesu. – Bill

+0

Bill, masz rację ... Ale jeśli masz napisać aplikację do zarządzania lojalnością, która pozwala patronom na kod PIN, musisz go użyć bez tych wcześniej zaprogramowanych kluczy .... Wcześniejszy model PINPad 1000SE - nie pamiętam na wierzch mojej głowy - pozwoliło ci uzyskać kod PIN i wysłać go jako czysty tekst. Późniejsze modele szyfrują kod PIN i nie możemy się do niego dostać ... –

Odpowiedz

2

Most CBC MAC Algorytmy są implementowane w dostawcy JCE BouncyCastle.

Spójrz: BouncyCastleProvider.java

Pewnie szuka DESEDEISO9797ALG1MACWITHISO7816-4PADDING, który jest aliasem dla DESEDEMAC64WITHISO7816-4PADDING realizowany tutaj (dobrze, że jest to specyficzna konfiguracja CBCBlockCipherMac pomocą DESedeEngine i ISO7816d4Padding, musisz skakać między niektórych klas, aby uzyskać pełny obraz): JCEMac.java

także rzucić okiem na jPos:

JCESecurityModule.java

a ich realizacja przyczyniła detaliczny algorytm MAC:

retail-mac-contributed-by-vsalaman.zip

0

Jestem całkiem pewny (IIRC), że trzeba zadzwonić TransformFinalBlock na końcu (na szyfratora).

0

Nie mogę odpowiedzieć na twój konkretny terminal, ale używam tego do testowania MAC.

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