代码之家  ›  专栏  ›  技术社区  ›  Tonher

向Mifare Classic 1k NFC标记写入和读取数据

  •  2
  • Tonher  · 技术社区  · 6 年前

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

    我找到了卡的钥匙和访问条件 this app :

    密钥:

    Keys

    访问条件:

    Access Conditions

    <uses-permission android:name="android.permission.NFC" /> 在我的舱单上。

    这是我的代码:

    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����������������������
    

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

    我还试图通过注释写入部分并将身份验证密钥A更改为,仅读取扇区0 MifareClassic.KEY_MIFARE_APPLICATION_DIRECTORY 这次我得到了一个日志:

    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
    

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

    1 回复  |  直到 5 年前
        1
  •  4
  •   Michael Roland    6 年前

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

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

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

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

    这有几个问题:

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

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

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