向 Mifare Classic 1k NFC 标签写入和读取数据
Write and read data to Mifare Classic 1k NFC tag
我正在尝试在 Mifare Classic 1k NFC 标签上读取和写入数据。
感谢this app,我找到了卡片的密钥和访问条件:
键:
准入条件:
<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") ;
}
}
当我尝试那样写和读时,我读的不是我写的。
这里是 logcat:
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 更改为 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);
然后,您尝试写入和读取块 0:
mfc.writeBlock(0, bWrite);
byte[] bRead = mfc.readBlock(0);
这有几个问题:
同时使用密钥A和密钥B进行认证是没有意义的,只有最后一次认证决定了标签的认证状态。由于所有扇区似乎都可以使用密钥 B 写入,因此您可以安全地使用第二行(仅 mfc.authenticateSectorWithKeyB()
)。
您对扇区 2 进行身份验证,该扇区由块 8、9、10 和 11 组成。写入和读取块 0 在该身份验证状态下没有意义。请注意,read/write 操作通常使用全局块编号。扇区仅用作 authentication/access 控制目的的逻辑单位。您可以使用 mfc.sectorToBlock()
和 mfc.getBlockCountInSector()
.
轻松地根据扇区编号计算块号
Block 0(在扇区0)是一个特殊的块,制造商块。它通常包含在生产过程中烧入标签的 UID、SAK 和制造商信息。该块是只读的,不能更改。因此,写入该块没有任何效果。
我正在尝试在 Mifare Classic 1k NFC 标签上读取和写入数据。
感谢this app,我找到了卡片的密钥和访问条件:
键:
准入条件:
<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") ;
}
}
当我尝试那样写和读时,我读的不是我写的。
这里是 logcat:
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 更改为 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);
然后,您尝试写入和读取块 0:
mfc.writeBlock(0, bWrite);
byte[] bRead = mfc.readBlock(0);
这有几个问题:
同时使用密钥A和密钥B进行认证是没有意义的,只有最后一次认证决定了标签的认证状态。由于所有扇区似乎都可以使用密钥 B 写入,因此您可以安全地使用第二行(仅
mfc.authenticateSectorWithKeyB()
)。您对扇区 2 进行身份验证,该扇区由块 8、9、10 和 11 组成。写入和读取块 0 在该身份验证状态下没有意义。请注意,read/write 操作通常使用全局块编号。扇区仅用作 authentication/access 控制目的的逻辑单位。您可以使用
mfc.sectorToBlock()
和mfc.getBlockCountInSector()
. 轻松地根据扇区编号计算块号
Block 0(在扇区0)是一个特殊的块,制造商块。它通常包含在生产过程中烧入标签的 UID、SAK 和制造商信息。该块是只读的,不能更改。因此,写入该块没有任何效果。