8

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

在使用 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) 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 等?我基本上需要从一个应用程序中获取一个文件。如果需要,我还可以提供一些使用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

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

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

Select APPLICATION: 9100
Read DATA: 91AE

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

4

1 回答 1

9

鉴于您从 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 中显示的访问条件)。

因此,为了读取此文件,您将需要实施身份验证过程。

于 2013-10-10T14:54:13.357 回答