android - 向 Mifare Classic 1k NFC 标签写入和读取数据

标签 android authentication permissions nfc mifare

我正在尝试在 Mifare Classic 1k NFC 标签上读取和写入数据。

通过this app我找到了该卡的 key 和访问条件:

按键:

Keys

访问条件:

Access Conditions

<uses-permission android:name="android.permission.NFC" />存在于我的 list 中。

这是我的代码:

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

if(tag != null) {
    Log.i("hey", Arrays.toString(tag.getTechList()));
    MifareClassic mfc = MifareClassic.get(tag) ;

    try {
        mfc.connect();
        boolean authA = mfc.authenticateSectorWithKeyA(2, MifareClassic.KEY_NFC_FORUM) ;
        boolean authB = mfc.authenticateSectorWithKeyB(2, MifareClassic.KEY_DEFAULT) ;
        Log.i("hey", "authA : " + authA) ;
        Log.i("hey", "authB : " + authB) ;

        if (authB && authA) {
            byte[] bWrite = new byte[16];
            byte[] hello = "hello".getBytes(StandardCharsets.US_ASCII);
            System.arraycopy(hello, 0, bWrite, 0, hello.length);
            mfc.writeBlock(0, bWrite);
            Log.i("hey", "write : " + Arrays.toString(bWrite));

            byte[] bRead = mfc.readBlock(0);
            String str = new String(bRead, StandardCharsets.US_ASCII);
            Log.i("hey", "read bytes : " + Arrays.toString(bRead));
            Log.i("hey", "read string : " + str);
            Toast.makeText(this, "read : " + str, Toast.LENGTH_SHORT).show();
            Log.i("hey", "expected : " + new String(bWrite, StandardCharsets.US_ASCII));
        }



        mfc.close();

    } catch (IOException e) {
        Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
        Log.i("hey", "Error") ;
    }


}

当我尝试这样写作和阅读时,我读到的并不是我写的。

这是日志猫:

I/hey: [android.nfc.tech.NfcA, android.nfc.tech.MifareClassic, android.nfc.tech.NdefFormatable]
I/hey: authA : true
    authB : true
I/hey: write : [104, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
I/hey: read byte : [-78, 0, 0, 0, 0, 0, -1, 7, -128, 105, -1, -1, -1, -1, -1, -1]
    read string : �������������i������
I/hey: expected : hello����������������������

我尝试了不同的字符集,但它没有改变任何东西。

我还尝试通过注释写入部分并将身份验证 key A 更改为 MifareClassic.KEY_MIFARE_APPLICATION_DIRECTORY 来仅读取扇区 0这次我得到了这个 Logcat:

I/hey: [android.nfc.tech.NfcA, android.nfc.tech.MifareClassic, android.nfc.tech.NdefFormatable] 
I/hey: authA : true
        authB : true 
I/hey: read bytes : [-123, -121, 0, 16, 18, 8, 4, 0, 1, -64, 62, -70, 74, 124, 78, 29]
        read string : �������>�J|N

知道如何修复它以正确写入和显示文本吗?

最佳答案

您首先向扇区 2 进行身份验证:

boolean authA = mfc.authenticateSectorWithKeyA(2, MifareClassic.KEY_NFC_FORUM);
boolean authB = mfc.authenticateSectorWithKeyB(2, MifareClassic.KEY_DEFAULT);

然后,您尝试写入和读取 block 0:

mfc.writeBlock(0, bWrite);
byte[] bRead = mfc.readBlock(0);

这有几个问题:

  1. 同时使用 key A 和 key B 进行身份验证是没有意义的。只有最后一次身份验证才能确定标签的身份验证状态。由于所有扇区似乎都可以使用 key B 写入,因此您可以安全地使用第二行(仅限 mfc.authenticateSectorWithKeyB())。

  2. 您对扇区 2 进行身份验证,该扇区由 block 8、9、10 和 11 组成。在该身份验证状态下,写入和读取 block 0 没有意义。请注意,读/写操作通常使用全局 block 编号。扇区仅用作用于身份验证/访问控制目的的逻辑单元。您可以使用 mfc.sectorToBlock()mfc.getBlockCountInSector() 轻松地根据扇区编号计算 block 编号。

  3. block 0(在扇区 0 中)是一个特殊 block ,即制造商 block 。它通常包含在生产过程中烧录到标签中的 UID、SAK 和制造商信息。该 block 是只读的,无法更改。因此,写入该 block 不会产生任何效果。

关于android - 向 Mifare Classic 1k NFC 标签写入和读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49879110/

相关文章:

c# - 登录表单没有正确失去焦点

linux - 禁止文件权限,但改名后可以访问

android - 我可以在 Android 平板电脑上为所有者以外的用户启用开发者模式吗?

android - 如何更改微调器文本大小和文本颜色?

java - 你如何检测双击拖动?

android - 适用于 Android 和 Amazon 的各种应用内结算选项有哪些

php - Symfony 4 : Login not working for token, 但适用于用户名和密码

python - Web 应用程序中的身份验证

php - nginx 本地网络服务器的所有权和权限

android - 如何恢复协程的真实调用轨迹?