• NFC (二)读写MifareClassic协议的NFC卡


    先了解一下MifareClassic协议

    在android sdk 的文档中,描述道 “all MifareClassic I/O operations will be supported, and MIFARE_CLASSIC NDEF tags will also be supported. In either case, NfcA will also be enumerated on the tag, because all MIFARE Classic tags are also NfcA.” 所以说NFCA协议是兼容MifareClassic 协议的, 我们可以通过NfcA在android的相关类来处理给予MifareClassic 的RFID卡。

    一般来说,给予MifareClassic的射频卡,一般内存大小有3种:

    1K: 16个分区(sector),每个分区4个块(block),每个块(block) 16个byte数据

    2K: 32个分区,每个分区4个块(block),每个块(block) 16个byte数据

    4K:64个分区,每个分区4个块(block),每个块(block) 16个byte数据

    对于所有基于MifareClassic的卡来说,每个区最后一个块叫Trailer,16个byte, 主要来存放读写该区的key,可以有A,B两个KEY,每个key长6byte,默认的key一般是FF 或 0,最后一个块的内存结构如下:

    Block 0  Data 16bytes
    Block 1  Data 16 bytes
    Block 2  Data 16 bytes
    Block 3  Trailer 16 bytes
     
    Trailer:
    Key A: 6 bytes
    Access Conditions: 4 bytes
    Key B: 6 bytes 
     
    所以在写卡的内存的时候,一般不能写每个sector的最后一个block,除非你有要修改KEY和访问权限的需求。如果KEY A 被你不小心修改掉了,而你不知道修改成什么,那与之对应的那个sector你就没有办法访问了。因为在MifareClassic中,如果你要读取数据,那么必须要有这个数据地址所在的sector的权限,这个权限就是这个sector的trailer的keyA或KEY B。
     
    读数据的例子:
    //tag 就是在上一篇中onNewIntent中获取的tag
    MifareClassic mc = MifareClassic.get(tag);
            short startAddress = 0;
            short endAddress = 5;
    
            byte[] data = new byte[(endAddress - startAddress + 1 ) * ByteCountPerBlock];
            
            try {            
                mc.connect();for (short i = startAddress; i <= endAddress; i++ ,time++) {
                    boolean auth = false;
                    short sectorAddress = getSectorAddress(i);
                    auth = mc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_DEFAULT);
                    if (auth){
                        
                        //the last block of the sector is used for KeyA and KeyB cannot be overwritted
                        short readAddress = (short)(sectorAddress == 0 ? i : i + sectorAddress);
                        
                        byte[] response = mc.readBlock(readAddress);
                        CombineByteArray(data, response, time * ByteCountPerBlock);
                    }
                    else{
                        throw new NfcException(NfcErrorCode.TemporaryError,
                                "Authorization Error.");
                    }
                }
    
                mc.close();
                
            }
            catch (NfcException ne) {
                throw ne;
            }
            catch (IOException e) {
                throw new NfcException(NfcErrorCode.TemporaryError,
                        "Get response, what it is not successfully.", e);
            }
            finally
            {
                try {
                    mc.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    写数据的例子:
     
    //tag 就是在上一篇中onNewIntent中获取的tag
    MifareClassic mc = MifareClassic.get(tag);
    
                try {
                    mc.connect();
                    boolean auth = false;
                    short sectorAddress = 0
                    auth = mc.authenticateSectorWithKeyA(sectorAddress,
                            MifareClassic.KEY_DEFAULT);
                    if (auth) {
                        //the last block of the sector is used for KeyA and KeyB cannot be overwritted
                        
                        mc.writeBlock(readAddress, dataTemp);
    
                        mc.close();
                    } 
                }finally
                {
                    try {
                        mc.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

    完整的代码示例在这里下载

    上一篇 NFC (一) 概述

  • 相关阅读:
    ASIX配置vlan tag能被wireshark获取
    翻译-cmake教程
    Manjaro打造开发环境
    Frida入门
    安卓应用启动底层执行逻辑
    集合框架
    oracle清除日志内存
    flutter widgets目录
    给设备添加udid
    5.class
  • 原文地址:https://www.cnblogs.com/haoxinyue/p/2479599.html
Copyright © 2020-2023  润新知