NFC(Near Field Communication),是在RFID的基础上发展而来的,工作在13.56MHz频率下,通过近距离接触实现数据交换。
本文介绍NFC标签最基础的知识:硬件的种类、内容的格式、常见的应用。
NFC标签的种类
根据 NFC Forum 标准,NFC标签有以下类型:
- Type 1 (T1T):基于 ISO/IEC 14443A 标准,多为Topaz芯片,容量小(96字节到2KB)。
- Type 2 (T2T):基于 ISO/IEC 14443-3 A 类标准,MIFARE和NTAG系列。
- Type 3 (T3T):基于 JIS X 6319-4 (FeliCa) 标准,日本Suica交通卡、香港八达通 等都基于这个标准。
- Type 4 (T4T):基于 ISO/IEC 14443-3 A/B 类标准,中国公交卡用到的CPU卡都基于这个标准。
- Type 5 (T5T):基于 ISO/IEC 15693 标准,适合长距离读取。
我们重点关注Type 2 (T2T)中的NTAG系列和MIFARE系列,这是日常生活中最常用的NFC标签类型。

MIFARE根据不同的安全等级,分为MIFARE Classic、MIFARE Plus、MIFARE DESFire等。
MIFARE存储的内容分为数据区和密钥区。其中,密钥区是不支持读取的,只能在芯片内部参与加密运算,这使得MIFARE卡很适合用做身份认证,如门禁卡、会员卡等。曾经的公交卡也是基于MIFARE,但由于MIFARE Classic 存在安全漏洞,现在的公交卡基本都改为CPU卡了。
NTAG系列是市面上最常用的NFC标签类型。分为NTAG203、NTAG213(144字节)、NTAG215(504字节)、NTAG216(888字节)等型号。
除了容量大小的差别,NTAG203不支持密码保护和读写锁功能,而NTAG213、NTAG215、NTAG216还支持密码保护和读写锁功能。写完内容后可以设置密码,防止他人修改;也可以把某些区域锁死,变成只读。但是,NTAG的密码在射频空中传输时是明文的(容易被专业设备空中窃听),且密码也很短,容易被暴力破解,整体上来说安全性不高。
NFC内容的格式
为什么有些NFC卡片,手机碰一下就能打开?比如打开某个App,或者访问某个网站。这涉及到一个NFC内容的标准格式规范:NDEF(NFC Data Exchange Format)。
NDEF格式
无论是 Android 还是 iOS,系统自带的NFC后台全局扫描功能,都只认NDEF格式。只有NDEF格式的NFC标签,手机才能在不借助任何第三方软件的情况下,直接打开对应操作。
NDEF是一种标准的数据交换格式。一个NDEF消息包含一条或多条记录。每条记录都包含类型、载荷等字段。手机读取到NDEF消息后,会依次读取每条记录,根据记录类型进行处理。
我们使用"小碰NFC"这个App来尝试读取一张典型的NTAG标签,内容如下图:

可以看到,这是一张NTAG216标签,存储的格式是NDEF,记录只有一条。我们点开这条记录查看详情,看到这条记录的Type是"U",这代表这条记录是一个URI记录。内容是 https://blog.oonne.com,用手机触碰一下这张标签,可以自动打开我的博客。
每条NDEF记录都有一个TNF(Type Name Format)和Type,可以理解为记录的主类别和子类别。通过这两个字段,触碰NFC标签的手机就知道要做哪些操作:打开链接、连接蓝牙、打开App等等。
非NDEF格式
NTAG系列的NFC标签通常存储NDEF格式的数据,而MIFARE系列的NFC标签通常存储二进制原始数据,或特定的专有数据格式。这些数据手机无法直接打开,需要通过专门的设备App来读取识别。这些格式没有统一的行业标准,完全由开发者或使用方根据业务需求自行定义规则。
手机NFC提供的能力
卡模拟功能
手机通过卡模拟模式,把自己变成一张NFC卡,让外部读卡器读取。这是手机刷门禁、刷公交、Apple Pay支付的基础。
当我们在手机上使用公交卡的时候,实际上模拟的是一张CPU卡,其中的加密信息都存在手机里,可以正常响应地铁公交读卡器的查询和交易请求。如果你换手机,需要把旧手机的公交卡"移入"新手机,本质上只是在用安全的方式传输CPU卡里的加密数据。
当我们用手机模拟门禁卡的时候,通常是模拟一张MIFARE卡。很多门禁系统,只验证卡的ID是否在门禁系统中,安全性非常低。此时手机只需要模拟ID即可,不需要去破解原有门禁卡的密钥。
读写NFC标签
手机作为读写器,主动发射电磁场,为NFC标签供电并读取或写入数据。
系统层面,Android和iOS都支持全局扫描NDEF格式的标签。开发层面,Android和iOS都提供NFC API,允许App读写NDEF消息。
点对点传输
两台NFC设备靠近后,建立双向连接,直接交换数据。早已被抛弃,现在已经没有人再使用了。现在各大厂商的"碰一下传文件"功能,本质上只是用NFC交换一下握手配对,剩下的数据传输都是通过蓝牙或wifi来完成的,与点对点传输模式毫无关系。
支付宝"碰一下"是怎么工作的?
贴在桌上的码(NFC标签)
这是日常生活中最常见的支付标签,手机碰一下能打开支付宝的付款界面,和扫码付款的体验几乎一致。我们使用"小碰NFC"这个App,来尝试读取一张支付宝的付款码标签,内容如下:

可以看到,这是一张NTAG标签,存储的格式是NDEF。从下往上看,记录有3条:
- 第一条记录TNF是 0x04(外部类型), Type是 android.com:pkg, 表示这是一个"打开App"的操作。内容是"com.eg.android.AlipayGphone",这是支付宝的包名。有一部分标签还会额外增加一条适用于鸿蒙系统的记录,系统在识别时,通常只会读取第一条匹配且有效的记录。
- 第二条记录是URI类型,内容是支付宝付款链接。手机根据上面两条记录,自动打开支付宝的时候,会把这个链接传给支付宝,从而直接跳转到付款界面。
在二维码支付的时代,可以通过中转链接判断UserAgent,做分别跳转,来实现”一个码同时支持微信支付和支付宝“。但碰一下打开什么App,取决于NDEF第一条记录中的"android.com:pkg"对应的包名。这就意味着一个标签只能对应一个App。这可能也是近几年支付宝大力推广碰一下的原因之一。
"碰一下"机器(POS终端)
支付宝的"碰一下"终端,是一个有源的NFC设备。机器端使用"卡模拟"的功能(Host Card Emulation, 简称HCE),来生成一个虚拟的NFC卡,依然是NDEF格式。手机触碰以后,同样识别到里面的链接,来打开支付界面。
可以看到,"碰一下"付款,与扫码付款的流程几乎完全一致,只不过把原先储存在二维码里的链接,直接储存在NFC标签里。通过NFC握手后,支付的安全性完全由后续手机或机器通过网络通信实现,与NFC标签没有关系了。