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=;i < ; i++)//我现在的卡包含45个blocks/pages
      {
        ((Mifare)card).Read(i, data, );
        readSB.AppendLine(Utility.ByteToHex(data, , data.Length));
      }
        tbRead.Text = readSB.ToString();
      }
    }
    catch (Exception ex)
    {
      MessageBox.Show(ex.Message);
    }
  }

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

2,解析

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

 C9       0A C9 5A      1D        E1
0A C9 5A 1D E1 A0 0C
1D E1 A0 0C 0F D1
E1 A0 0C 0F D1 0B
A0 0C 0F D1 0B 6E
0F D1 0B 6E
0B 6E FE
6E FE
FE
FE (以下省略...)

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


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信息。

 C9
0A C9 5A
1D
E1 00 A0 0C
0F D1
0B
6E FE

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

 (Tag: Lock Control TLV)
(Length: bytes)
A0 0C (Value: Information on position and function of lock bytes)
(Tag: NDEF Message TLV)
0F (Length: bytes)
D1 0B 6E
FE (Tag: Terminator TLV; has no length field)

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

NDEF message:
D1 (Header byte of record )
(Type length: byte)
0B (Payload length: bytes)
(Type: "T")
6E (Payload field)

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

The payload field:
(Status byte: Text is UTF- encoded, Language code has a length of bytes)
6E (Language code: "en")
(Text: "")

可以用在线工具来验证一下 “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());
} byte[] cardUid = cardBytes.Take().ToArray();
string cardUidStr = Utility.ByteToHex(cardUid, , cardUid.Length); byte[] cardMaker = cardBytes.Skip().Take().ToArray();
string cardMakerStr = Utility.ByteToHex(cardMaker, , cardMaker.Length); byte[] memoryBytes = cardBytes.Skip().ToArray(); byte lockControlByte = memoryBytes[];
byte lockByteCount = memoryBytes[];//how many bytes are the lock bytes
byte[] lockBytes = memoryBytes.Skip().Take(lockByteCount).ToArray(); int nedfLengthByteIndex = + lockByteCount + + ;
byte ndefLength = memoryBytes[nedfLengthByteIndex]; if (ndefLength == )//Tag empty
return string.Empty; byte[] ndefBytes = memoryBytes.Skip(nedfLengthByteIndex + ).Take(ndefLength).ToArray(); byte payloadHeader = ndefBytes[];
byte payloadTypeLength = ndefBytes[];
byte payloadLength = ndefBytes[];
byte[] payloadType = ndefBytes.Skip().Take(payloadTypeLength).ToArray(); byte[] payloadBytes = ndefBytes.Skip( + payloadType.Length).Take(payloadLength).ToArray(); byte languageCodeLength = payloadBytes[];
byte[] languageCode = payloadBytes.Skip().Take(languageCodeLength).ToArray();
byte[] tag = payloadBytes.Skip( + languageCode.Length).Take(payloadLength - languageCode.Length - ).ToArray(); string tagHex= Utility.ByteToHex(tag , , 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(パソリ)

Windows读取NXP MiFare Ultralight C类型NFC卡片的信息的更多相关文章

  1. 射频识别技术漫谈(16)——Mifare UltraLight

    Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本.小容量的卡片.低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片 ...

  2. php 读取文件头判断文件类型的实现代码

    php代码实现读取文件头判断文件类型,支持图片.rar.exe等后缀. 例子: <?php $filename = "11.jpg"; //为图片的路径可以用d:/uploa ...

  3. Windows上常见的集中布尔类型的比较

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:Windows上常见的集中布尔类型的比较.

  4. Windows Phone 同步方式获取网络类型

    原文:Windows Phone 同步方式获取网络类型 在Windows Phone 开发中有时候需要获取设备当前连接网络的类型,是Wifi,还是2G,3G,或者4G,SDK中提供获取网络类型的API ...

  5. python3 在 windows 读取路径多了一个\u202a 是咋回

    python3 在 windows 读取路径多了一个\u202a 是咋回事

  6. wpf prism4 出现问题:无法加载一个或多个请求的类型。有关更多信息,请检索 LoaderExceptions 属性。

    WPF Prism 框架 程序 出现 问题: 无法加载一个或多个请求的类型.有关更多信息,请检索 LoaderExceptions 属性. 1.开始以为是配置的问题,找了半天,最后原来是有个依赖类库没 ...

  7. 无法加载一个或多个请求的类型。有关更多信息,请检索 LoaderExceptions 属性。

    新建一个MVC4的项目,引用DAL后,将DAL的连接字符串考入: <connectionStrings>     <add name="brnmallEntities&qu ...

  8. “无法加载一个或多个请求的类型。有关更多信息,请检索 LoaderExceptions 属性 “之解决

    今天在学习插件系统设计的时候遇到一个问题:“System.Reflection.ReflectionTypeLoadException: 无法加载一个或多个请求的类型. 于是百度一下,很多内容都差不多 ...

  9. Sqlserver查询表结构信息-字段说明、类型、长度等信息

    Sqlserver 中查询表结构信息-字段说明.类型.长度等信息综合语法. SELECT 表名 = d.name,--case when a.colorder=1 then d.name else ' ...

随机推荐

  1. 洛谷P2059 [JLOI2013]卡牌游戏

    题目描述 N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把 ...

  2. 【转载】深入理解Linux文件系统

      1.rm-rf删除目录里的文件后,为什么可以恢复? 首先创建一个空目录test,目录的blocksize为4096字节 为了空目录还是4096?首先,目录的大小取决它所包含的文件的inode(访问 ...

  3. PCB 规则引擎之JSON对象查看器

    在PCB规则引擎开发中,JavaScript V8引擎是处理业务逻辑的, 当然业务逻辑需要数据支撑才行,  即需有将数据推进入到V8引擎.目前这边数据传输到JavaScript V8引擎以C# Mod ...

  4. Tempter of the Bone------剪枝

    看了好多别人的  代码,最终还是 感觉 这种代码的风格适合我  下面附上代码 /* 首先 应该充满信心! 先写出来 自己的程序 然后慢慢改 , 如果是 答题思路错误的话 借鉴别人的 代码 再写 */ ...

  5. JavaScript--编程练习1

    使用JS完成一个简单的计算器功能.实现2个输入框中输入整数后,点击第三个输入框能给出2个整数的加减乘除. 提示:获取元素的值设置和获取方法为:例:赋值:document.getElementById( ...

  6. 发布 Windows 服务

    1. 如何新建 Windows 服务 打开VS,“新建项目”-->“windows 桌面”-->“windows 服务”: http://www.cnblogs.com/sorex/arc ...

  7. Linq学习(二)-本次学习用到的资料

    本次学习用到的数据库初始化脚本如下 use KMS create table Blog_User ( UserId ,1), NickName ), CreateTime datetime ) cre ...

  8. python 根据数组生成图片

    array = np.asarray(allBigPng, dtype=np.uint8)image = Image.fromarray(array, 'RGBA') image.save(outpu ...

  9. dubbo之延迟暴露

    延迟暴露 如果你的服务需要预热时间,比如初始化缓存,等待相关资源就位等,可以使用 delay 进行延迟暴露. 延迟 5 秒暴露服务 <dubbo:service delay="5000 ...

  10. (原创)HyperPacer使用技巧之集合点设置

    版权声明:本文为原创文章,转载请先联系并标明出处 性能测试中,我们可以模拟最真实的用户操作来建立性能模型,但是这种模拟是相对的.譬如12306网站春运开始后每一天都是高峰,这种高负载情况会持续一至两个 ...