Android NFC IsoDep 读取文件内容

Posted

技术标签:

【中文标题】Android NFC IsoDep 读取文件内容【英文标题】:Android NFC IsoDep read file content 【发布时间】:2013-10-10 13:06:50 【问题描述】:

我正在尝试从 ISO/IEC 14443 Type A 卡中读取一些信息。

使用安卓应用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) 0x35,(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),但我无法理解如何为 P1P2 实现正确的值.


编辑

使用 NFC TagInfo 的卡的标签类型:ISO/IEC 14443-4 智能卡、Mifare DESFire EV1 (MF3ICD81)

源代码中使用的 SELECT 命令实际上并没有失败,而是返回了 9000 响应。所以这就是为什么我认为一切正常。

您提到 NFC TagInfo 没有为 DF 名称等提供 正确 值。值 0x313538343546 是否正确,您是如何做到的?找到了吗?

你能给我一个简短的描述吗,我怎样才能得到我想要的数据?是否有任何其他安卓应用程序可用于读取正确的 DF 名称、AID 等?我基本上需要从 ONE 应用程序中获取 ONE 文件。如果需要,我还可以提供一些使用 NFC TagInfo 收集的信息的屏幕截图。


编辑 2

我已经重写了命令,但是(正如你所建议的)将它们保存在 APDU 包装器中。因此我最终得到了两个不同的命令,一个用于选择应用程序,另一个用于选择文件

private final byte[] NATIVE_SELECT_APP_COMMAND = new byte[]

    (byte) 0x90, (byte) 0x5A, (byte) 0x00, (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, (byte) 0x00, (byte) 0x00, 7,  // READ
    (byte) 0x01,                                            // FILE ID
    (byte) 0x00, (byte) 0x00, (byte) 0x00,                  // OFFSET
    (byte) 0x00, (byte) 0x00, (byte) 0x00,                  // LENGTH
    (byte) 0x00
;

搜索原生 Mifire-Desfire 命令教程没有成功,所以我坚持以下教程:http://noobstah.blogspot.de/2013/04/mifare-desfire-ev1-and-android.html

本教程提供了一个卡认证,我禁用了它,并且还使用了 transceive 方法,在我看来这不是执行本机命令的正确方法?哪种方法,甚至可能是代码片段,用于执行本机命令?我应该使用哪个 Android-Class?

我已经重写了教程中提供的类并上传到pastebin。执行完课程后,我得到了以下结果。

Select APPLICATION: 9100
Read DATA: 91AE

在这一点上,我很困惑,不知道下一步我应该做什么。实际上是错误还是我应该在查询中执行哪些更改以获得我想要的数据?

【问题讨论】:

【参考方案1】:

鉴于您从 NFC TagInfo 中提取的信息以及您尝试使用的命令,我假设该卡是 MIFARE DESFire EV1。对吗?

关于您的选择命令: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 发出选择应用程序命令(注意不同的字节顺序!):

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

获取应用程序,包括其 DF 名称:

906D000000

选择您的应用程序:

905A0000035F841500

获取 DESFire FID:

906F000000

获取 ISO FID:

9061000000

您始终可以使用 IsoDep 对象的 transceive() 方法。无论如何都使用 IsoDep(即 ISO/IEC 14443-4)(对于本机 DESFire 命令、包装本机命令和 ISO 7816-4 命令)。

您从卡收到的错误代码 (0xAE) 表示身份验证错误(有关详细信息,请参阅此数据表:DESFire)。因此,该文件允许经过身份验证的只读(参见 NFC TagInfo 中显示的访问条件)。

因此,为了读取此文件,您需要执行身份验证程序。

【讨论】:

感谢您的快速回复!我刚刚编辑了我的帖子,在它的底部,还有其他信息。 感谢您的帮助,但我仍然卡住了,我刚刚编辑了我的帖子并提供了更多信息。 我已经更新了答案。很遗憾,我无法帮助您实施身份验证程序。 感谢您的回答,并感谢您提供错误代码和成功代码的链接!它有望引导我找到解决方案。此外,我不知道我实际上必须对自己进行身份验证 - 我会阅读规范!

以上是关于Android NFC IsoDep 读取文件内容的主要内容,如果未能解决你的问题,请参考以下文章

Android NFC:使用 transceive() 时出现异常“transceive failed”

ISO 14443 A 型卡使用 Android 读/写

android手机中如何写入NFC程序?怎样能读到一张卡

Android -- 读取NFC卡号

在android平板中如何进行NFC通信,就是通过rfid读卡器连接到平板的USB后,读取的内容显示到平板上

NFC阅读器没有在android中连续读取NFC标签