PN532 MiFare Ultralight C Взаимная аутентификация

Кому-нибудь удалось получить взаимную аутентификацию со сверхлегкой картой C, работающей с использованием этого чипа? Я понимаю процедуру аутентификации, но глядя на набор команд в руководстве по чипам и пробуя несколько вещей, я не думаю, что это на самом деле возможно, но подумал, что опубликую здесь, прежде чем отказаться от набора микросхем и вернуться к использованию кодировщика CJS для проверка

заранее спасибо


person watersa8    schedule 08.11.2014    source источник


Ответы (2)


Да, можно выполнить взаимную аутентификацию с помощью Mifare Ultralight C. Используйте следующую процедуру:

ШАГ 1. Отправьте команду запуска проверки подлинности. (1A 00) на карту

ШАГ 2: Карта генерирует 8-байтовое случайное число RndB. Это случайное число шифруется DES/3DES с помощью диверсифицированного ключа, обозначаемого ek(RndB), и затем передается на терминал.

ШАГ 3 Терминал выполняет операцию дешифрования DES/3DES для полученного ek(RndB) и, таким образом, извлекает RndB. Затем RndB сдвигается влево на 8 бит (первый байт перемещается в конец RndB), что дает RndB’. Теперь терминал сам генерирует 8-байтовое случайное число RndA. Этот RndA объединяется с RndB’ и дешифруется с использованием DES/3DES (дешифрование двух блоков связывается в цепочку с использованием режима отправки Cipher Block Chaining (CBC)). Этот токен dk(RndA + RndB’) отправляется на карту.

ШАГ 4: Карта выполняет шифрование DES/3DES для полученного токена и, таким образом, получает RndA + RndB’. Теперь карта может проверить отправленный RndB’, сравнив его с RndB’, полученным путем поворота исходного RndB влево на 8 бит внутри. Успешная проверка подтверждает карте, что карта и терминал имеют один и тот же секрет (ключ). Если проверка не удалась, карта останавливает процедуру аутентификации и возвращает сообщение об ошибке. Поскольку карта также получила случайное число RndA, сгенерированное терминалом, она может выполнить операцию поворота влево на 8 битов на RndA, чтобы получить RndA’, который снова шифруется, в результате чего получается ek(RndA’). Этот токен отправляется на терминал.

ШАГ 5: Терминал выполняет дешифрование DES/3DES для полученного ek(RndA’) и, таким образом, получает RndA’ для сравнения с RndA’, повернутым внутри терминала. Если сравнение не удается, терминал выходит из процедуры и может остановить карту.

ШАГ 6. Карта устанавливает состояние аутентификации как "Аутентифицировано".

Какая часть доставила вам проблемы?

person Lewis Munene    schedule 17.03.2017
comment
Спасибо за ответ, я где-то читал, что это возможно, и решил это после нескольких часов проверки кода, когда я понял, что установил количество байтов в одном из моих ответов на чтение на неправильное значение, поэтому оставлял данные в буфер. Простая ошибка, которая приводит к гигантской головной боли. - person watersa8; 27.03.2017
comment
Можете ли вы опубликовать свой код для новичков, если эта некромантия темы не слишком большая головная боль? - person Motes; 11.04.2018
comment
@Motes, см. ответ ниже. - person Lewis Munene; 02.05.2018

Пример исходного кода C:

typedef unsigned char byte;

int mutual_authentication( const byte *diversifiedKey )
{
    byte cmd[256], response[256];
    int cmdLen, responseLen;

    //Send 1A00
    cmd[0] = 0x1A;
    cmd[1] = 0x00;
    cmdLen = 2;
    int ret = send_command( cmd, cmdLen, response, &responseLen );

    //Get ekRndB
    byte ekRndB[8], rndB[8];

    memcpy(ekRndB, response, 8);
    //Decrypt ekRndB with diversifiedKey
    des_ISO_decrypt( diversifiedKey, ekRndB, rndB, 8 );

    //PCD Generates RndA
    byte randA[8] = "\x33,\x54,\x2A,\x87,\x21,\x00,\x77,\x98";//random numbers
    byte rndARndBComplement[16], ekRndARndBComplement[16];

    // Append RndA and RndB' ( RndB' is generated by rotating RndB one byte to the left )
    // after the status byte.
    memcpy(&rndARndBComplement[0],rndA,8);
    memcpy(&rndARndBComplement[8],&rndB[1],7);  // bytes 1 to 7
    rndARndBComplement[15] = rndB[0];           // byte 0

    // Apply the DES send operation to the 16 argument bytes before sending the second frame to the PICC
    des_ISO_encrypt(diversifiedKey, rndARndBComplement, ekRndARndBComplement, 16);

    cmd[0] = 0xAF;
    memcpy(&cmd[1], ekRndARndBComplement, 16);
    cmdLen = 17;

    ret = send_command( cmd, cmdLen, response, &responseLen );

    byte ekRndAComplement[8], rndAComplement[8], finalOutput[8];

    memcpy(&ekRndAComplement[0], &response[1], 8);
    des_ISO_decrypt(diversifiedKey, ekRndAComplement, rndAComplement, 8);

    memcpy(&finalOutput[1], &RndAComplement[0], 7);
    finalOutput[0] = rndAComplement[7];

    //compare the received RndA with the one we originally had
    return memcmp(&finalOutput[0], &rndA[0], 8);
}

Примечание. У вас должна быть собственная реализация send_command() (в зависимости от устройства чтения карт), des_ISO_decrypt() и des_ISO_encrypt() (в зависимости в вашей библиотеке DES).

person Lewis Munene    schedule 02.05.2018