ISO 9797-1 Алгоритм 1 [CBC-MAC] в C #

Кажется, что есть 6 вариантов алгоритма CBC-MAC. Я пытался сопоставить алгоритм MAC на PINPad 1000SE [который по руководству является ISO 9797-1 Алгоритм 1].

Я получил отличное начало отсюда .

И я кодировал алгоритм, как показано ниже:

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

Затем я обнаружил, что есть 3 схемы заполнения, и та, которая дала мне старт, не обязательно может быть правильной. Руководство снова пришло мне на помощь. Кажется, устройство только колодки с 0s. Дополнительный блок также нигде не упоминается, поэтому я внес следующие изменения:

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

Нет дополнительного блока (если мод 0 [делится на 8], не меняйте длину массива)

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

Первоначальное предложение требовало, чтобы я расшифровал на втором шаге ... но Валерий здесь предполагает, что он полностью зашифрован. Поэтому я изменил Decrypt на Encrypt. Но я все еще не могу получить необходимый MAC ...

Руководство говорит для ключа "6AC292FAA1315B4D8234B3A3D7D5933A" [поскольку ключ должен быть 16 байтов, я решил, что ключ здесь шестнадцатеричная строка, поэтому я взял значения байтов 6A, C2, 92, FA ... новый байт [] {106, 194, 146, ...] MAC должен быть 7B, 40, BA, 95 [4 байта], если сообщение является [0x1a + байтовый массив MENTERODOMETER]

Может кто-нибудь помочь? Пожалуйста?


Поскольку Pinpad требует, чтобы первый символ в сообщении был 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);
}

Я вызываю код выше с этим входом:

var result = pad.CalculateAugmentedMAC("MENTERODOMETER", new byte[] { 106, 194, 146, 250, 161, 49, 91, 77, 130, 52, 179, 163, 215, 213, 147, 58 });
11.12.2008 19:00:58
Любопытно. Зачем вам нужно участвовать в расшифровке данных PINPad? Рабочий процесс PINPad предназначен для отправки зашифрованных данных непосредственно в банк продавца с использованием ключей DUKPT, сгенерированных банком и установленных в PINPad поставщиком PINPad. Даже до того момента, когда мы писали программное обеспечение для непосредственного управления пользовательским интерфейсом и другими действиями PINPad, мы никогда не были в состоянии это сделать, и при этом нам не нужно было шифровать / дешифровать конверт с зашифрованными данными PIN, предоставляемый как часть процесса.
Bill 18.09.2009 13:50:42
Билл, вы правы ... Но если вам нужно было написать приложение для управления лояльностью, которое позволяет пользователям вводить PIN-код, вам нужно использовать его без этих предварительно запрограммированных ключей ... Более ранняя модель PINPad 1000SE - не помню верхняя часть моей головы - позволил вам получить PIN-код и отправить его в виде открытого текста. Более поздние модели шифруют PIN-код, и мы не можем получить его ...
Vyas Bharghava 28.09.2009 15:37:11
3 ОТВЕТА

Большинство алгоритмов CBC MAC реализованы в JCE-провайдере BouncyCastle .

Посмотрите на: BouncyCastleProvider.java

Вы, вероятно, ищете DESEDEISO9797ALG1MACWITHISO7816-4PADDING, который является псевдонимом DESEDEMAC64WITHISO7816-4PADDING, реализованным здесь (ну, это специфическая конфигурация CBCBlockCipherMac с использованием DESedeEngine и ISO7816d4Padding, вам придется переходить между некоторыми классами, чтобы получить полную картину): JCEMac.java

Также взгляните на jPos:

JCESecurityModule.java

и их реализация розничного алгоритма MAC:

retail-mac-contributed-by-vsalaman.zip

2
22.09.2009 12:46:34

Я почти уверен (IIRC), что вам нужно позвонить TransformFinalBlockв конце (для каждого шифровщика).

0
22.09.2009 12:51:30

Не могу ответить на ваш конкретный терминал, но я использую это для проверки MAC.

public static byte[] GenerateMAC(byte[] key, byte[] data)
{
    using (MACTripleDES mac = new MACTripleDES(key))
        return mac.ComputeHash(data);
}
0
4.08.2010 15:49:46