如何实现NFC标签仅允许自有App进行写入操作
实现NFC标签仅允许自有应用写入的可行方案
注:不存在绝对无法破解的防护方案,以下是基于NFC Forum标准实现的权限配置,可拦截绝大多数第三方应用的随意修改,若需对抗专业硬件破解需选用带硬件加密的专用标签
方案一:普通NTAG系列标签(NTAG213/215/216,成本最低、兼容性最好)
这是市面最常用的NFC标签类型,不要开永久只读锁(开了之后包括你自己的应用都没法改内容),按以下步骤配置:
- 配置标签硬件级写密码:给标签设置4字节的私有访问密码,修改标签的AUTH0寄存器,将写保护起始地址设为用户数据区首页,配置规则为所有写入操作必须先通过密码校验,读操作无限制。普通第三方应用扫描标签时可以正常读取URL跳转,但因为不知道密码,发送写入指令会直接被标签硬件拒绝。
- 自有应用写入逻辑:你的应用执行写入前,先发送
PWD_AUTH指令完成密码校验,再执行NDEF内容写入,写完无需解锁,保持写保护状态即可。核心校验指令示例:// 密码验证指令,<4字节PWD>替换为你自定义的私有密码,<2字节PACK>为密码校验成功后的响应校验值 0xFF 0x00 0x00 0x00 0x08 0xD4 0x42 0x1B <4字节PWD> <2字节PACK> - 加一层应用层签名校验:写入URL时额外加一条自定义NDEF记录,用你应用内置的私有密钥对URL内容做HMAC-SHA256签名,把签名值存在这条自定义记录里。后续你的应用写入前先校验已有签名是否匹配,就算有人用特殊硬件绕过密码改了内容,你的应用也能识别到篡改,不会执行后续覆盖写入逻辑。核心写入代码片段(Android端):
// 密钥不要明文存在Java/Kotlin层,建议放到NDK层做混淆,避免反编译泄露 private const val INNER_KEY = "your_app_unique_builtin_key" fun buildNdefContent(targetUrl: String): NdefMessage { val urlRecord = NdefRecord.createUri(targetUrl) val sign = hmacSha256(INNER_KEY, targetUrl) // 自定义签名记录,类型字段用你自己的应用包名避免冲突 val signRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.yourapp.nfc:sign".toByteArray(), null, sign ) return NdefMessage(arrayOf(urlRecord, signRecord)) }
方案二:Type 4加密NFC标签(安全性更高,适合商用场景)
如果对安全性要求更高,直接选用Type 4规格的NFC标签:
- 初始化标签时自定义一个专属AID(应用标识符),给标签内的NDEF存储文件配置访问规则:读权限设为公开访问,保证所有设备能正常读取URL跳转;写权限仅对持有对应AID的应用开放。
- 你的应用在写入前先选中这个私有AID建立安全通道,才能获得写入权限,第三方应用不知道专属AID,根本无法触发写入流程,权限判断完全在标签硬件层完成,比NTAG的密码防护等级更高,缺点是标签成本比普通NTAG高30%左右。
避坑提醒
- 不要用Mifare Classic卡做权限控制,这类卡的加密算法早已被公开破解,第三方工具几秒就能读出密码篡改内容。
- 标签密码、内置签名密钥不要硬编码在应用的Java/Kotlin代码层,建议做NDK混淆、密钥拆分存储,避免反编译后泄露。
- 永久只读锁只适合不需要后续修改内容的场景,一旦开启无法撤销,不要在需要迭代更新URL的场景下使用。
如果需要对抗专业级NFC读写硬件的破解,建议选用搭载国密/SE安全单元的加密NFC标签,把写入权限和标签芯片唯一UID绑定,破解成本会高到没有商用价值。
内容的提问来源于stack exchange,提问作者caktasnino
相关产品推荐
相关产品推荐

