博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows读取NXP MiFare Ultralight C类型NFC卡片的信息
阅读量:6407 次
发布时间:2019-06-23

本文共 5467 字,大约阅读时间需要 18 分钟。

1,读取

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

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

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

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

解压并运行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 470A C9 5A 841D 48 00 00E1 10 12 00 01 03 A0 0C  34 03 0F D101 0B 54 0265 6E 32 3031 38 31 3032 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
cardContentList) { List
cardBytes = new List
(); 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; }

 

 

参考链接:

转载于:https://www.cnblogs.com/AlvinLiang/p/9889992.html

你可能感兴趣的文章
【后缀数组】
查看>>
图片缩放裁剪
查看>>
jquery ajax 回调函数的值alert出来[object Object] 解决方法
查看>>
JQuery选择器总结
查看>>
MySQL安装详解(V5.5 For Windows)
查看>>
Android单例模式
查看>>
Log4php 使用心得
查看>>
十三香_百度百科
查看>>
paip.网页右键复制菜单限制解除解决方案
查看>>
string.Format 格式化时间,货币
查看>>
Kerberos和NTLM - SQL Server
查看>>
记github上搭建独立域名的免费博客的方法过程
查看>>
Web设计之网页布局CSS技巧
查看>>
iOS key value coding kvc在接收json数据与 model封装中的使用
查看>>
Android 滑动效果入门篇(二)—— Gallery
查看>>
Revit二次开发示例:DesignOptions
查看>>
Entity Framework 系统约定配置
查看>>
优秀设计:纹理在网页设计中的20个应用示例
查看>>
C++ 关键字 explicit, export, mutable
查看>>
生成指定范围的一组随机数并求平均值
查看>>