为ISO 14443 NFC标签设置密码保护遇问题求助
搞定FM11NT021 NFC标签密码设置的坑
先理清楚FM11NT021的密码逻辑
FM11NT021是ISO14443A协议的标签,密码保护涉及三个关键配置:
- PWD(密码):固定4字节,存储在地址
0x2C-0x2F - PACK(密码验证响应):固定2字节,存储在地址
0x30-0x31 - AUTH0:1字节,存储在地址
0x2B,用来定义「从哪个地址开始需要密码验证」——比如你存128字节NDEF的区域是0x00-0x7F,把AUTH0设为0x80,就只有配置区(0x28及以后)需要验证,不会影响NDEF的正常读写;要是设成0x00,全区域都要密码,包括写AUTH0本身,很容易触发死循环。
你遇到的两个核心问题:
- 写入PWD、PACK后再写AUTH0时出现「连接丢失」
- 调用
writeNdefWithPass或authenticatePassword返回的PACK为[0,0]
一步步排查修正
1. 先确认命令和地址有没有写错
FM11NT021的配置区不能用NDEF写入命令操作,必须用块写入命令(0xA2)。很多人踩坑就是误用了NDEF的写入方法,直接导致报错。
给你一个正确的配置区写入代码示例:
async function setTagPassword(passwordBytes, packBytes, auth0Value) { try { // 先校验参数长度:密码必须4字节,PACK必须2字节 if (passwordBytes.length !== 4 || packBytes.length !== 2) { throw new Error('密码需为4字节,PACK需为2字节'); } // 1. 写入密码:块地址0x0B(对应字节0x2C-0x2F) await NfcManager.transceive([0xA2, 0x0B, ...passwordBytes]); // 2. 写入PACK:块地址0x0C(对应字节0x30-0x33),不能覆盖后2字节的其他配置位 const originalPackBlock = await NfcManager.transceive([0x30, 0x0C]); // 先读取原有块内容 const newPackBlock = [...packBytes, originalPackBlock[2], originalPackBlock[3]]; // 替换前2字节为目标PACK await NfcManager.transceive([0xA2, 0x0C, ...newPackBlock]); // 3. 写入AUTH0:块地址0x0A(对应字节0x28-0x2B),替换第4字节(索引3)为目标AUTH0值 const originalAuth0Block = await NfcManager.transceive([0x30, 0x0A]); const newAuth0Block = [originalAuth0Block[0], originalAuth0Block[1], originalAuth0Block[2], auth0Value]; await NfcManager.transceive([0xA2, 0x0A, ...newAuth0Block]); return true; } catch (err) { console.error('设置密码失败:', err); return false; } }
2. 解决「连接丢失」问题
- 操作顺序不能乱:必须严格遵循「写PWD→写PACK→写AUTH0」的顺序。要是先写AUTH0,一旦AUTH0生效,后续写PWD/PACK就需要密码验证,直接卡壳。另外AUTH0的值别设太小,参考前面的建议,避开NDEF存储区,避免写AUTH0时触发密码验证。
- 控制命令间隔:Android平台NFC标签的连接超时很短,连续的
transceive命令要尽量快速执行,别加不必要的延迟。实在需要等待,加100ms以内的小延迟即可:await new Promise(resolve => setTimeout(resolve, 100))。 - 排查标签供电:部分廉价标签连续写入时会出现供电不足,导致断连。可以分步测试,每写完一步就读取配置区确认,再执行下一步。
3. 解决PACK返回[0,0]问题
- PACK写入地址错误:FM11NT021的PACK在
0x30-0x31,属于块0x0C的前2字节,不能直接覆盖整个块,必须保留后2字节的其他配置位(比如锁定位)。上面的代码已经处理了这个问题,写完后可以用读命令确认0x30-0x31的值是否为你设置的PACK。 - 认证前未激活标签:调用
authenticatePassword前,必须确保标签处于激活状态,先执行await NfcManager.requestTechnology(NfcTech.IsoDep)或NfcTech.Ndef,否则标签无响应,会返回默认的[0,0]。 - 密码参数错误:如果传入的密码不是4字节的数组/Uint8Array,或者密码值错误,标签也会返回
[0,0]。先确认密码参数的格式和长度正确。
4. 平台权限与兼容性注意
- Android:清单文件中必须添加
<uses-permission android:name="android.permission.NFC" />,还要添加TECH_DISCOVERED过滤,指定支持ISO14443A和FM11NT021的技术类型。 - iOS:iOS对NFC低级命令限制较多,react-native-nfc-manager可能无法直接操作标签配置区,需要用原生CoreNFC写扩展,或者换用iOS支持的标签操作方法。
测试小技巧
- 先用NFC Tools这类第三方APP手动设置密码、PACK、AUTH0,确认标签本身功能正常。
- 分步测试代码:先只写PWD,读配置区确认写入成功;再写PACK,读确认;最后写AUTH0。
- 开启调试日志:
NfcManager.setLogLevel('debug'),查看底层发送的命令和标签响应,快速定位问题点。
内容的提问来源于stack exchange,提问作者Koen Schoffner
相关产品推荐
相关产品推荐

