MIFARE Plus EV2 SL3自定义认证实现中mplus_firstAuth_f2步骤0x06错误排查求助
MIFARE Plus EV2 SL3自定义认证实现中mplus_firstAuth_f2步骤0x06错误排查求助
大家好,我是第一次接触MIFARE Plus这类卡片,最近遇到了一个棘手的问题,想请各位帮忙排查一下。
背景情况
我刚入手了一台型号为P18Q的终端,它支持MIFARE Plus卡片的多种认证方式。供应商告诉我需要自行实现加密算法来和工作在SL3模式下的卡片通信,完成指定扇区的认证。我用NXP官方库的时候,认证、读写卡片都能成功,但因为这台终端没有标准的Android NFC阅读器,只能通过APDU和外部终端通信,所以没办法用官方库,只能自己写实现。
问题现象
现在的情况是:认证第一步我能成功收到卡片返回的挑战,但在第二步(也就是调用mplus_firstAuth_f2发送我的AES密钥相关响应时),一直收到0x06错误码。我跟着步骤走,第一步检测卡片、激活卡片、PPS协商都没问题,但到发送加密后的响应就失败了。
我的实现代码
下面是我写的测试方法:
public void test_MifarePlus() { final int CID = 0; final int fsdi = PICC_FSD_256; int DRI = PICC_BITRATE_TXRX_106K; int DSI = PICC_BITRATE_TXRX_106K; clearLog(); appendLog("Iniciando autenticación Mifare Plus..."); try { appendLog(">>> Paso 1: Detectando tarjeta..."); String uid = detectNfcCard(); if (uid == null || uid.isEmpty()) { appendLog("Error: No se detectó tarjeta NFC"); return; } appendLog("Tarjeta detectada. UID: " + uid); appendLog("\n>>> Paso 2: Activando tarjeta..."); String ATS = activateTypeACard(fsdi, CID); if (ATS == null || ATS.length() < 2) { appendLog("Error: Fallo en activación de tarjeta"); return; } byte[] atsBytes = ByteArrayTools.hexStringToByteArray(ATS); int[] rates = PICC_ParseRate(atsBytes); DRI = rates[0]; DSI = rates[1]; appendLog("ATS recibido: " + ATS); appendLog("Parámetros negociados - DRI: " + DRI + ", DSI: " + DSI); appendLog("\n>>> Paso 3: Solicitud PPS..."); int ppsStatus = requestPPS(CID, DRI, DSI); if (ppsStatus != 0) { appendLog("Error: Fallo en PPS (Código: " + ppsStatus + ")"); return; } appendLog("PPS exitoso"); appendLog("\n>>> Paso 4: Configurando autenticación SL3..."); P18QMifarePlus channel = new P18QMifarePlus(); MifarePlus mifarePlus = new MifarePlus(channel); byte[] keyAES; try { keyAES = ByteArrayTools.hexStringToByteArray(AESKey); if (keyAES == null || keyAES.length != 16) { appendLog("Error: Clave AES inválida. Debe ser de 16 bytes"); return; } } catch (IllegalArgumentException e) { appendLog("Error: Formato de clave AES inválido"); return; } appendLog("\n>>> Paso 5: Autenticación F1..."); int blockToAuth = 0x4002; byte[] encryptedChallenge = mifarePlus.mplus_firstAuth_f1(blockToAuth); if (encryptedChallenge == null || encryptedChallenge.length < 16) { appendLog("Error: Challenge inválido o autenticación F1 fallida"); return; } appendLog("Challenge cifrado recibido: " + ByteArrayTools.byteArrayToHexString(encryptedChallenge)); byte[] randB; try { randB = aesDecrypt(Arrays.copyOf(encryptedChallenge, 16), keyAES); if (randB == null || randB.length != 16) { appendLog("Error: Descifrado de RAND_B fallido"); return; } } catch (Exception e) { appendLog("Error al descifrar RAND_B: " + e.getMessage()); return; } appendLog("RAND_B descifrado: " + ByteArrayTools.byteArrayToHexString(randB)); byte[] randB_rot = rotateLeftByte(randB); byte[] randA = generateSecureRandom(16); byte[] responseData = concatenateArrays(randA, randB_rot); appendLog("RAND_A generado: " + ByteArrayTools.byteArrayToHexString(randA)); appendLog("RAND_B rotado: " + ByteArrayTools.byteArrayToHexString(randB_rot)); appendLog("\n>>> Paso 6: Autenticación F2..."); byte[] encryptedResponse; try { encryptedResponse = aesEncrypt(responseData, keyAES); } catch (Exception e) { appendLog("Error al cifrar respuesta F2: " + e.getMessage()); return; } appendLog("Datos a enviar (cifrados): " + ByteArrayTools.byteArrayToHexString(encryptedResponse)); byte[] authResponse = mifarePlus.mplus_firstAuth_f2(encryptedResponse); if (authResponse == null || authResponse.length == 0) { appendLog("Error: Respuesta de autenticación F2 inválida"); return; } if (authResponse[0] != (byte) 0x90) { appendLog("Autenticación fallida. Código de error: " + String.format("%02X", authResponse[0])); return; } appendLog("\nAutenticación SL3 completada con éxito!"); appendLog("Respuesta final: " + ByteArrayTools.byteArrayToHexString(authResponse)); } catch (Exception e) { appendLog("Error crítico: " + e.toString()); e.printStackTrace(); } finally { try { int removalStatus = removeCPUCard(); // 原代码此处截断,保留现有逻辑 } catch (Exception e) { appendLog("Error al remover tarjeta: " + e.getMessage()); } } }
我的疑惑
我是不是在mplus_firstAuth_f2步骤的参数处理上出错了?比如加密的方式、发送的数据格式不对?或者是AES密钥的使用有问题?因为第一次做这类卡片的开发,实在摸不准哪里错了,希望有经验的朋友能给我一些提示,谢谢!
内容来源于stack exchange
相关产品推荐
相关产品推荐

