在使用Android应用程序NFC TagInfo分析卡片后,我发现应用程序(AID:15845F)具有我需要的特定文件(文件ID:01).
我已经设法连接到卡并选择应用程序.
String action = getIntent().getAction(); if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { Tag tagFromIntent = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG); Log.i(TAG,Arrays.toString(tagFromIntent.getTechList())); IsoDep isoDep = IsoDep.get(tagFromIntent); try { isoDep.connect(); byte[] SELECT = { (byte) 0x00,// CLA = 00 (first interindustry command set) (byte) 0xA4,// INS = A4 (SELECT) (byte) 0x04,// P1 = 04 (select file by DF name) (byte) 0x0C,// P2 = 0C (first or only file; no FCI) (byte) 0x06,// Lc = 6 (data/AID has 6 bytes) (byte) 0x31,(byte) 0x35,(byte) 0x38,(byte) 0x34,(byte) 0x46 // AID = 15845F }; byte[] result = isoDep.transceive(SELECT); Log.i(TAG,"SELECT: " + bin2hex(result)); if (!(result[0] == (byte) 0x90 && result[1] == (byte) 0x00)) throw new IOException("could not select application"); byte[] GET_STRING = { (byte) 0x00,// CLA Class (byte) 0xB0,// INS Instruction (byte) 0x00,// P1 Parameter 1 (byte) 0x00,// P2 Parameter 2 (byte) 0x04 // LE maximal number of bytes expected in result }; result = isoDep.transceive(GET_STRING); Log.i(TAG,"GET_STRING: " + bin2hex(result)); } }
但我的第二个查询失败,错误代码为:6A86(参数P1-P2不正确).我已经搜索了很多并找到了不同的文档(例如:http://bit.ly/180b6tB),但我无法理解,我如何为P1和P2实现正确的值.
编辑
使用NFC TagInfo的卡的标签类型:ISO / IEC 14443-4智能卡,Mifare DESFire EV1(MF3ICD81)
源代码中使用的SELECT命令实际上没有失败,而是返回了9000响应.所以这就是我认为一切正常的原因.
您提到NFC TagInfo没有为DF名称等提供正确的值.值0x313538343546是否正确,您是如何找到它的?
你能给我一个简短的描述,我怎么能得到我想要的数据?有没有其他Android应用程序,我可以用来读取正确的DF名称,AID等?我基本上需要从一个应用程序中获取一个文件.如果需要,我还可以提供使用NFC TagInfo收集的信息的一些屏幕截图.
编辑2
我已经重写了命令,但(正如你所建议的那样)将它们保存在APDU包装器中.因此,我最终得到了两个不同的命令,一个用于选择应用程序,另一个用于选择文件.
private final byte[] NATIVE_SELECT_APP_COMMAND = new byte[] { (byte) 0x90,(byte) 0x5A,(byte) 0x00,3,// SELECT (byte) 0x5F,(byte) 0x84,(byte) 0x15,(byte) 0x00 // APPLICATION ID }; private final byte[] NATIVE_SELECT_FILE_COMMAND = new byte[] { (byte) 0x90,(byte) 0xBD,7,// READ (byte) 0x01,// FILE ID (byte) 0x00,// OFFSET (byte) 0x00,// LENGTH (byte) 0x00 };
搜索本机Mifire-Desfire命令的教程不成功,所以我坚持以下教程:http://noobstah.blogspot.de/2013/04/mifare-desfire-ev1-and-android.html
本教程提供了卡身份验证,我禁用了它,并且还使用了收发方法,据我所知,这不是执行本机命令的正确方法吗?哪个方法,甚至代码snippit,用于执行本机命令?我应该使用哪种Android-Class?
我已经重写了教程中提供的类并将其上传到pastebin.执行完课程后,我得到了以下结果.
Select APPLICATION: 9100 Read DATA: 91AE
解决方法
关于您的选择命令:NFC TagInfo当前不读取DESFire EV1的ISO命令集中使用的DF名称值.因此,我假设为此应用程序设置的DF名称实际上是0x313538343546,否则SELECT命令应该失败.但请注意,此值绝不可从NFC TagInfo中显示的DESFire AID中导出!事实上,DF名称是在应用程序创建期间定义的单独值. (这与以前的DESFire版本不同.)
关于READ BINARY命令:您使用的命令意味着您之前选择了一个文件.但是,您只选择了该应用程序.因此,您需要为数据文件发出SELECT命令或在READ BINARY命令中使用短文件ID:
byte[] READ_BINARY = { (byte) 0x00,// CLA Class (byte) 0xB0,// INS Instruction (byte) 0x80,// P1 (indicate use of SFI) (byte) 0x01,// P2 (SFI = 0x01) (byte) 0x04 // LE maximal number of bytes expected in result };
但是,当谈到DESFire(EV1)时,我建议你坚持使用DESFire本机命令集(直接或包装)而不是使用ISO 7816-4 APDU.
使用本机命令集,您可以获得MIFARE DESFire的全部功能.通过将本机DESFire命令嵌入到ISO 7816-4 APDU结构中来完成命令包装.包装命令如下所示:
0x90 CMD 0x00 0x00 LEN CMD-PARAM 0x00
其中CMD是本机DESFire命令,CMD-PARAM是命令参数.回应是:
[DATA] 0x91 STATUS
其中status是本机DESFire状态代码.如果STATUS为0xAF,则可以通过发出以下命令获取剩余的响应数据:
0x90 0xAF 0x00 0x00 0x00
因此,在您的情况下,您将为您的应用程序0x15845F发出一个select应用程序命令(请注意不同的字节顺序!):
0x90 0x5A 0x00 0x00 3 0x5F 0x84 0x15 0x00 |SELECT| |APPLICATION ID|
然后,您要读取数据文件0x01(整个文件,从偏移量0开始):
0x90 0xBD 0x00 0x00 7 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 |READ| |FILE| OFFSET | LENGTH |
关于如何获取应用程序的ISO DF名称和ISO FID的问题,您可以尝试以下命令:
选择主应用程序:
905A00000300000000
906D000000
选择你的申请:
905A0000035F841500
获取DESFire FID:
906F000000
获取ISO FID:
9061000000
您始终可以使用IsoDep对象的transceive()方法.无论如何都使用IsoDep(即ISO / IEC 14443-4)(对于本机DESFire命令,对于包装的本机命令和对于ISO 7816-4命令).
您从卡(0xAE)收到的错误代码表示验证错误(有关详细信息,请参阅此数据表:DESFire).因此,该文件允许经过身份验证的只读(请参阅NFC TagInfo中显示的访问条件).
因此,为了读取此文件,您需要实现身份验证过程.