Хороший день.
Несколько дней назад я приобрел терминал (модель P18Q), который поддерживает различные методы аутентификации для карт Mifare Plus. Поставщик сообщил мне, что мне нужно внедрить свои собственные алгоритмы шифрования для связи с картой, которая работает в режиме SL3, и для аутентификации в определенном секторе. Однако при использовании моей пользовательской реализации - где я отправляю свой ключ AES вместе с ответом на вызов - я последовательно сталкиваюсь с ошибкой во время процесса MPLUS_FIRSTAUTH_F2. < /P>
Кто -нибудь знает, правильно ли я выполняю аутентификацию? К сожалению, я не могу использовать официальную библиотеку NXP на этом терминале, так как в нем отсутствует стандартный читатель Android NFC. Вместо этого он связывается только через Apdus с внешним терминалом. Я делаю что -то не так? Это моя первая работа с этим типом карты. < /P>
public void test_MifarePlus() {
int CID = 0;
int fsdi = PICC_FSD_256;
int DRI = PICC_BITRATE_TXRX_106K;
int DSI = PICC_BITRATE_TXRX_106K;
int st;
clearLog();
appendLog("Please present MifarePlus card >>>>>>>>>>>>>>>");
try {
String uid = detectNfcCard();
if (uid == null) {
appendLog("Error: No se detectó la tarjeta MifarePlus.");
return;
}
appendLog("Detectada tarjeta con UID = " + uid);
getPICCAtrribute();
String ATS = activateTypeACard(fsdi, CID);
if (ATS == null) {
appendLog("Error: Falló activación.");
return;
}
appendLog("Activación exitosa.");
if (ATS.length() > 2) {
byte[] ats = ByteArrayTools.hexStringToByteArray(ATS);
int[] DRI_DSI = PICC_ParseRate(ats);
DRI = DRI_DSI[0];
DSI = DRI_DSI[1];
appendLog("==> Solicitud de PPS: DRI =" + DRI + " DSI = " + DSI);
st = requestPPS(CID, DRI, DSI);
if (st != 0) {
appendLog("Error: Falló solicitud de PPS.");
return;
}
appendLog("PPS exitoso.");
}
getPICCAtrribute();
P18QMifarePlus channel = new P18QMifarePlus();
MifarePlus mifarePlus = new MifarePlus(channel);
byte[] keyAES = ByteArrayTools.hexStringToByteArray(AESKey);
int blockToAuth = 0x4002;
byte[] challenge = mifarePlus.mplus_firstAuth_f1_cc(blockToAuth);
if (challenge == null) {
appendLog("SL3 auth f1 failed");
return;
}
appendLog("SL3 auth f1 success, encrypted challenge: " + ByteArrayTools.byteArrayToHexString(challenge));
// 1. Decrypt RAND_B
byte[] randB = aesDecrypt(challenge, keyAES);
appendLog("Decrypted RAND_B: " + ByteArrayTools.byteArrayToHexString(randB));
// 2. Rotate RAND_B
byte[] randB_rot = rotateLeft(randB);
appendLog("Rotated RAND_B: " + ByteArrayTools.byteArrayToHexString(randB_rot));
// 3. Generate RAND_A
byte[] randA = new byte[16];
new SecureRandom().nextBytes(randA);
appendLog("Generated RAND_A: " + ByteArrayTools.byteArrayToHexString(randA));
// 4. Concatenate RAND_A || rotate(RAND_B)
byte[] toEncrypt = new byte[32];
System.arraycopy(randA, 0, toEncrypt, 0, 16);
System.arraycopy(randB_rot, 0, toEncrypt, 16, 16);
// 5. Encrypt with AES
byte[] responseF2 = aesEncrypt(toEncrypt, keyAES);
appendLog("SL3 nextAuth f2 input (AES): " + ByteArrayTools.byteArrayToHexString(responseF2));
// 6. Send F2 command
byte[] resF2 = mifarePlus.mplus_firstAuth_f2_cc(responseF2);
if (resF2 == null) {
appendLog("SL3 auth f2 failed: respuesta nula");
return;
}
if (resF2.length == 0) {
appendLog("SL3 auth f2 failed: respuesta vacía");
return;
}
if (resF2[0] != (byte) 0x90) {
appendLog("SL3 auth f2 failed: código de estado SW1 = " + String.format("%02X", resF2[0]));
appendLog("Respuesta completa: " + ByteArrayTools.byteArrayToHexString(resF2));
return;
}
st = removeCPUCard();
if (st != 0) {
appendLog("MifarePlus test error");
} else {
appendLog("MifarePlus test Success");
}
} catch (Exception e) {
appendLog("Fallo en el proceso MifarePlus: " + e.toString());
}
}
private byte[] aesEncrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(data);
}
private byte[] aesDecrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(data);
}
private byte[] rotateLeft(byte[] input) {
byte[] output = new byte[input.length];
for (int i = 0; i < input.length; i++) {
output = (byte) ((input > 7) & 0x01));
}
return output;
}
public byte[] mplus_firstAuth_f1_cc(int key) throws Exception {
byte bloque1 = (byte) ( ( key >> 8 ) & 0xFF );
byte bloque2 = (byte) ( ( key ) & 0xFF );
byte[] apdu = new byte[4];
apdu[0] = 0x70;
apdu[1] = bloque2;
apdu[2] = bloque1;
apdu[3] = 0x00;
byte[] response = mplusMgr.sendApduControlCommand(apdu);
if ( response == null ) {
return null;
}
if ( response[0] == (byte) 0x90 ) {
return Arrays.copyOfRange(response, 1, response.length);
} else {
return null;
}
}
public byte[] mplus_firstAuth_f2_cc(byte[] data) throws Exception {
if ( data == null ) {
return null;
}
byte[] apdu = new byte[data.length + 1];
apdu[0] = (byte) 0x72;
System.arraycopy(data, 0, apdu, 1, data.length);
byte[] response = mplusMgr.sendApduControlCommand(apdu);
return response;
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... us-ev2-sl3
Аутентификация с Mifare Plus EV2 SL3 ⇐ JAVA
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение