如何使用Node.js访问符合ISO14443A标准的Mifare智能卡
使用Node.js读取Omnikey 5321 CL读卡器上ISO14443A标准Mifare卡的实现方案
前置依赖准备
- 先安装Omnikey 5321 CL官方驱动,确保系统正常识别读卡器设备
- 安装PC/SC标准的Node.js绑定库
@pokusew/pcsclite,该库原生支持ISO14443A协议的Mifare卡操作:npm install @pokusew/pcsclite - Linux系统需提前安装
pcscd服务和libpcsclite-dev依赖包
核心实现逻辑
你提到的三个参数会分别在选应用、块认证环节传入,可参考以下可运行代码,按实际参数替换对应变量即可:
const pcsclite = require('@pokusew/pcsclite'); const pcsc = pcsclite(); // 以下参数按实际场景替换 const AID = Buffer.from('F00102', 'hex'); // 3位十六进制格式Application ID,示例为F00102 const KEY = Buffer.from([0x12, 0x34, 0x56, 0x78]); // 32位整数格式密钥,转换为4字节Buffer传入 const KEY_ID = 0x60; // 十六进制格式keyid,Mifare卡通用密钥A为0x60、密钥B为0x61 const TARGET_BLOCK = 0x04; // 需要读取的卡块编号,按需调整 pcsc.on('reader', (reader) => { console.log('已识别读卡器:', reader.name); reader.on('status', (status) => { const stateChange = reader.state ^ status.state; // 检测到卡片插入 if (stateChange & reader.SCARD_STATE_PRESENT) { console.log('检测到Mifare卡插入'); reader.connect({ share_mode: reader.SCARD_SHARE_SHARED }, (err, protocol) => { if (err) { console.error('卡片连接失败:', err); return; } // 第一步:选择指定AID的应用 const selectApdu = Buffer.concat([ Buffer.from([0x00, 0xA4, 0x04, 0x00]), Buffer.from([AID.length]), AID ]); reader.transmit(selectApdu, 256, protocol, (err, res) => { if (err || res.slice(-2).toString('hex') !== '9000') { console.error('AID选择失败:', err || '响应码异常' + res.slice(-2).toString('hex')); return; } console.log('AID选择成功'); // 第二步:使用指定密钥和keyid认证目标块 const authApdu = Buffer.concat([ Buffer.from([0xFF, 0x86, 0x00, 0x00, 0x05]), Buffer.from([0x01, 0x00, TARGET_BLOCK, KEY_ID, 0x00]), KEY ]); reader.transmit(authApdu, 256, protocol, (err, res) => { if (err || res.slice(-2).toString('hex') !== '9000') { console.error('块认证失败:', err || '响应码异常' + res.slice(-2).toString('hex')); return; } console.log('块认证成功'); // 第三步:读取目标块数据 const readApdu = Buffer.from([0xFF, 0xB0, 0x00, TARGET_BLOCK, 0x10]); reader.transmit(readApdu, 256, protocol, (err, res) => { if (err || res.slice(-2).toString('hex') !== '9000') { console.error('块读取失败:', err || '响应码异常' + res.slice(-2).toString('hex')); return; } // 输出读取到的16字节块数据,去掉末尾2字节状态码 const blockData = res.slice(0, -2).toString('hex'); console.log('读取到的块数据:', blockData); // 操作完成断开连接 reader.disconnect(reader.SCARD_LEAVE_CARD, () => {}); }); }); }); }); } }); }); pcsc.on('error', (err) => { console.error('PCSC服务异常:', err); });
注意事项
- 32位整数密钥转换为Buffer时需要注意和卡片要求的字节序一致,默认按大端转换即可
- 若认证失败,优先检查密钥正确性、目标块是否有对应密钥的读取权限
- 不同厂商的专用Mifare卡可能会有自定义APDU指令,若通用指令不生效可参考厂商提供的卡片接口文档调整
内容的提问来源于stack exchange,提问作者Troy
相关产品推荐
相关产品推荐

