Расшифровка данных зашифрованных данных DUKPT

Как говорится в названии, я пытаюсь дешифровать зашифрованные данные DUKPT, поступающие из сканера с поддержкой DUKPT.

У меня есть стандарт ANSI (X9.24) для DUKPT и успешно реализована возможность генерировать IPEK из KSN и BDK. Кроме того, я успешно реализовал возможность генерировать левый и правый MAC-запрос и ответные ключи с помощью XORing ключей шифрования PIN-кода. Наконец, я могу генерировать EPB.

Здесь я не понимаю, как сгенерировать запрос и ответ MAC из ключей L/R, которые я создал.

Наконец, как только я доберусь до этого шага, что будет дальше? Когда у меня есть ключ, который расшифровывает данные дорожки, отправленные устройством с поддержкой DUKPT?

Я знаю о Thales Simulator и jPOS. Мой код в настоящее время ссылается на симулятор Thales, чтобы выполнить всю свою работу. Но процесс дешифрования файла просто не возвращает ожидаемые данные.

Если кто-то может предложить некоторое представление о дешифровке данных трека, это было бы очень полезно.

http://thalessim.codeplex.com/

http://jpos.org/

Ответ 1

Я потратил слишком много времени на изучение ужасной спецификации X9.24 и, наконец, получил шифрование и дешифрование, работая с примерами моих продавцов, и маркетинг быстро решил переключить поставщиков. Поскольку это стандарт, вы бы подумали, что реализация anybodys будет одинаковой. Я хочу. Во всяком случае, существуют вариации в отношении того, как все реализовано. Вы должны изучить мелкий шрифт, чтобы убедиться, что вы работаете так же, как и с вашей стороны.

Но это не ваш вопрос.

Сначала, если вам необходимо расшифровать дорожку данных с кредитной карты, вы, вероятно, заинтересованы в создании ключа, который расшифрует данные на основе оригинального секретного ключа базовой деривации. Это не имеет никакого отношения к генерации MAC и упоминается только в этой ужасной спецификации. Вам необходимо сгенерировать IPEK для этого серийного номера и идентификатора устройства и повторно применять "Необратимый процесс генерации ключей" из спецификации, если биты устанавливаются в счетной части полного серийного номера ключа из HSM.

Эта часть моего кода выглядит так: (Извините за длинный список в публикации.)

/*
 * Bit "zero" set (this is a 21 bit register)(ANSI counts from the left)
 * This will be used to test each bit of the encryption counter
 * to decide when to find another key.
 */
testBit=0x00100000;
/*
 * We have to "encrypt" the IPEK repeatedly to find the current key
 * (See Section A.3).  Each time we encrypt (generate a new key),
 * we need to use the all prior bits to the left of the current bit.
 * The Spec says we will have a maximum of ten bits set at any time
 * so we should not have to generate more than ten keys to find the
 * current encryption key.
 */
cumBits=0;
/*
 * For each of the 21 possible key bits,
 * if it is set, we need to OR that bit into the cumulative bit
 * variable and set that as the KSN count and "encrypt" again.
 * The encryption we are using the goofy ANSI Key Generation
 * subroutine from page 50.
 */
for(int ii=0; ii<21; ii++)
{
    if( (keyNumber&testBit) != 0)
    {
        char ksr[10];
        char eightByte[8]={0};

        cumBits |= testBit;
        ksn.count=cumBits;   /* all bits processed to date */

        memcpy(ksr, &ksn,10);       /* copy bit structure to char array*/
        memcpy(crypt,&ksr[2],8);    /* copy bytes 2 through 9 */

        /*
         * Generate the new Key overwriting the old.
         * This will apply the "Non-reversible Key Generation Process"
         * to the lower 64 bits of the KSN.
         */
        keyGen(&key, &crypt, &key);
    }
    testBit>>=1;
}

Где keyNumber - текущий счетчик из ksn ksn - это 80-битная структура, которая содержит 80-битный серийный номер ключа из HSM crypt - это 64-битный блок данных, который у меня есть типа DES_cblock, так как я использую openSSL. key - это 128-битная двойная структура DES_cblock. Процедура keyGen почти дословно из локальной подпрограммы "Необратимая генерация ключа" на странице 50 спецификации.

В конце этого ключевая переменная будет содержать ключ, который может использоваться для расшифровки, почти. Парни, которые писали спецификацию, добавили некоторое "вариантное" поведение к ключу, чтобы держать нас на своих пальцах. Если ключ используется для дешифрования потока данных, такого как дорожка кредитной карты, вам понадобятся байты XOR 5 и 13 с 0xFF и Triple DES, которые шифруют ключ сам (режим ECB). Мой код выглядит так:

DOUBLE_KEY keyCopy;
char *p;
p=(char*)&key;
p[ 5]^=0xff;
p[13]^=0xff;
keyCopy=key;
des3(&keyCopy, (DES_cblock *)&key.left,  &key.left);
des3(&keyCopy, (DES_cblock *)&key.right, &key.right);

Если вы используете это для дешифрования PIN-кода, вам понадобятся XOR-байты 7 и 15 с 0xFF. (Я не уверен на 100%, что это не следует применять и для режима потока, но мой поставщик оставляет его.)

Если это ПИН-блок, он будет зашифрован с помощью 3-DES в режиме ECB. Если это поток данных, он будет зашифрован в режиме CBC с нулевым вектором инициализации.

(Я упоминал, что я не очень забочусь о спецификации?) Интересно отметить, что сторона шифрования может использоваться в небезопасном защищенном от несанкционированного доступа модуле защиты, если серверная сторона (выше) запоминает и отклоняет ключи, которые были использованы ранее. Технология довольно аккуратная. Спецификация ANSI оставляет желать лучшего, но технология в порядке.

Удачи. /Боб Брайан

Ответ 2

Для шифрования данных вариант 0000000000FF0000.0000000000FF0000, поэтому вам нужно XOR-байты 5 и 13 вместо 7 и 15. Кроме того, вам нужно выполнить дополнительный шаг самошифрования 3DES для каждой ключевой части (слева и справа).

Вот соответствующий код в jPOS  https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java#L1843-1856