• Windows读取NXP MiFare Ultralight C类型NFC卡片的信息


    1,读取

    我们需要外接一个NFC Reader让Windows可以读取NFC卡片的内容。

    因为特殊原因,我们选择了Sony rc-s380 NFC Reader。相关介绍

    我们需要下载并安装NFC Port Software,以便我们可以顺利使用上述NFC Reader。

    安装之后,我们需要去Github获取一个NFC Port Software的.Net封装包:tijins/NfcLib

    解压并运行nfc_lib_sample之后我们可以看到这样一个WindowFrom程序。

    因为现在要读取的卡类型试MIFARE,所以我们勾选正确的CheckBox,其他设置保持不变,依次点击上述三个橘色方框按钮。

    在红色箭头所指的方向就能看到第一个block的十六进制字符串的数据。

    为了读取卡片所有block/page的信息,我们将btRead_Click的代码稍稍修改为: 

    private void btRead_Click(object sender, EventArgs e)
    {
      byte block = (byte)nudBlock.Value;
      try
      {
        byte[] data = null;
        data = new byte[NfcLib.MF_BLOCK_LENGTH];
        if (card is Mifare)
        {
          StringBuilder readSB = new StringBuilder();
          for(byte i=0;i < 45; i++)//我现在的卡包含45个blocks/pages
          {
            ((Mifare)card).Read(i, data, 0);
            readSB.AppendLine(Utility.ByteToHex(data, 0, data.Length));
          }
            tbRead.Text = readSB.ToString();
          }
        }
        catch (Exception ex)
        {
          MessageBox.Show(ex.Message);
        }
      }

    有个小遗憾就是,如果NFC Reader没有连接的时候启动app会抛出异常,而如果app已经启动再拔出然后插入NFC Reader又会无法再读卡除非重启app或者重新初始化。这个需要有点改进。

    2,解析

    根据上述步骤,我们得到了某张卡的信息如下:

    04 C9 02 47     0A C9 5A 84     1D 48 00 00     E1 10 12 00 
    0A C9 5A 84     1D 48 00 00     E1 10 12 00     01 03 A0 0C 
    1D 48 00 00     E1 10 12 00     01 03 A0 0C     34 03 0F D1 
    E1 10 12 00     01 03 A0 0C     34 03 0F D1     01 0B 54 02 
    01 03 A0 0C     34 03 0F D1     01 0B 54 02     65 6E 32 30 
    34 03 0F D1     01 0B 54 02     65 6E 32 30     31 38 31 30 
    01 0B 54 02     65 6E 32 30     31 38 31 30     32 35 FE 00 
    65 6E 32 30     31 38 31 30     32 35 FE 00     00 00 00 00 
    31 38 31 30     32 35 FE 00     00 00 00 00     00 00 00 00 
    32 35 FE 00     00 00 00 00     00 00 00 00     00 00 00 00 
    00 00 00 00     00 00 00 00     00 00 00 00     00 00 00 00 
                                        (以下省略...)

    然后,我们对它做一点移位:

    
    
    04 C9 02 47     0A C9 5A 84     1D 48 00 00     E1 10 12 00 
              0A C9 5A 84     1D 48 00 00     E1 10 12 00     01 03 A0 0C 
                        1D 48 00 00     E1 10 12 00     01 03 A0 0C     34 03 0F D1 
                                  E1 10 12 00     01 03 A0 0C     34 03 0F D1     01 0B 54 02 
    01 03 A0 0C 34 03 0F D1 01 0B 54 02 65 6E 32 30           34 03 0F D1 01 0B 54 02 65 6E 32 30 31 38 31 30                     01 0B 54 02 65 6E 32 30 31 38 31 30 32 35 FE 00                               65 6E 32 30 31 38 31 30 32 35 FE 00 00 00 00 00
    31 38 31 30 32 35 FE 00 00 00 00 00 00 00 00 00           32 35 FE 00 00 00 00 00 00 00 00 00 00 00 00 00                     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

    可以看出,每一行只有第一列是我们需要的tag信息。

    04 C9 02 47
    0A C9 5A 84
    1D 48 00 00
    E1 10 12 00

    01 03 A0 0C 34 03 0F D1 01 0B 54 02 65 6E 32 30 31 38 31 30 32 35 FE 00

    前面的四行是卡的UID以及制造商等信息。我们只需要关心下半段的数据。

    01 (Tag: Lock Control TLV)
    03 (Length: 3 bytes)
    A0 0C 34 (Value: Information on position and function of lock bytes)
    03 (Tag: NDEF Message TLV)
    0F (Length: 15 bytes)
    D1 01 0B 54 02 65 6E 32 30 31 38 31 30 32 35 
    FE (Tag: Terminator TLV; has no length field)
    00

    所以,我们得到了NDEF message:D1 01 0B 54 02 65 6E 32 30 31 38 31 30 32 35

    NDEF message:
    D1 (Header byte of record 1)
    01 (Type length: 1 byte)
    0B (Payload length: 11 bytes)
    54 (Type: "T")
    02 65 6E 32 30 31 38 31 30 32 35 (Payload field)

    我们再分析最为关键的payload field,如下:

    The payload field:
    02 (Status byte: Text is UTF-8 encoded, Language code has a length of 2 bytes)
    65 6E (Language code: "en")
    32 30 31 38 31 30 32 35 (Text: "20181025")

    可以用在线工具来验证一下 “32 30 31 38 31 30 32 35 ”

    最后,上述步骤,用写C#的实现如下(不保证所有Mifare卡适用):

    private string GetNfcTag(List<byte[]> cardContentList)
            {
                List<byte> cardBytes = new List<byte>();
                foreach(byte[] rowCardContent in cardContentList)
                {
                    cardBytes.AddRange(rowCardContent.Take(4));                
                }
    
                byte[] cardUid = cardBytes.Take(8).ToArray();
                string cardUidStr = Utility.ByteToHex(cardUid, 0, cardUid.Length);
    
                byte[] cardMaker = cardBytes.Skip(8).Take(8).ToArray();
                string cardMakerStr = Utility.ByteToHex(cardMaker, 0, cardMaker.Length);
    
                byte[] memoryBytes = cardBytes.Skip(16).ToArray();
    
                byte lockControlByte = memoryBytes[0];
                byte lockByteCount = memoryBytes[1];//how many bytes are the lock bytes
                byte[] lockBytes = memoryBytes.Skip(2).Take(lockByteCount).ToArray();
    
                int nedfLengthByteIndex = 1 + lockByteCount + 1 + 1;
                byte ndefLength = memoryBytes[nedfLengthByteIndex];
    
                if (ndefLength == 0)//Tag empty
                    return string.Empty;
    
                byte[] ndefBytes = memoryBytes.Skip(nedfLengthByteIndex + 1).Take(ndefLength).ToArray();
    
                byte payloadHeader = ndefBytes[0];
                byte payloadTypeLength = ndefBytes[1];
                byte payloadLength = ndefBytes[2];
                byte[] payloadType = ndefBytes.Skip(3).Take(payloadTypeLength).ToArray();
    
                byte[] payloadBytes = ndefBytes.Skip(3 + payloadType.Length).Take(payloadLength).ToArray();
    
                byte languageCodeLength = payloadBytes[0];
                byte[] languageCode = payloadBytes.Skip(1).Take(languageCodeLength).ToArray();
                byte[] tag = payloadBytes.Skip(1 + languageCode.Length).Take(payloadLength - languageCode.Length - 1).ToArray();
    
    
                string tagHex= Utility.ByteToHex(tag , 0, tag .Length);
                string tagStr = Encoding.UTF8.GetString(tag);
                return tagStr;
            }

    参考链接:

    How to read binary blocks of mifare card?

    Reading a NFC Mifare card raw data in android

    tijins/NfcLib

    About the NDEF Format

    MIFARE Ultralight 系列

     RC-S380 非接触ICカードリーダー/ライター PaSoRi(パソリ)

  • 相关阅读:
    spring @resource @ Autowired
    mysql 。。。
    MYSQL
    oracle sql 性能 优化
    tomcat 解析(五)-Tomcat的核心组成和启动过程
    tomcat 解析(四)-处理http请求过程
    tomcat 解析(三)-启动框架
    tomcat 解析(二)-消息处理过程
    tomcat 解析(一)-文件解析
    我发起并创立了一个 C 语言编译器 开源项目 InnerC
  • 原文地址:https://www.cnblogs.com/AlvinLiang/p/9889992.html
Copyright © 2020-2023  润新知