最近好多朋友私信我想问小程序M1卡的读写问题,现在我给大家伙详细的剖析一下流程。
首先了解一下M1卡的基础知识
M1卡的内存图谱
我们把M1的内存区比作一个硬盘,它的16个扇区就相当于把硬盘分区分了A、B、C...等16个磁盘,每个磁盘上又创了四个文件(块0,块1,块2,块3),每个块都是用16个字节的16进制存放数据
块3:存放了当前扇区的密钥A(占用0-5字节)、密钥B(占用10-15字节)、和各个块的访问控制权限(占用6-9字节)
块0~块2:存放用户自定义的数据
认证:
认证是M1进行读取和写入之前必须处理的操作,如果你要操作的块读写只需要密钥A的认证,那就只要做一次密钥A的认证就可以进行读写了,这完全取决于上面说的访问控制权限,关于访问控制本文就不细讲了,想了解的可以去百度学习一下。
指令:
文章来源:https://www.toymoban.com/news/detail-844467.html
小程序实现M1的认证读取:
//请阅读如下代码注释文章来源地址https://www.toymoban.com/news/detail-844467.html
let adapter;//定义一个NFC适配器
let mifare;
adapter = wx.getNFCAdapter();
adapter.startDiscovery({
success:function(){
console.log('开启NFC适配器成功。');
},
fail:function(res){
console.log('开启NFC适配器失败!');
if(res.errCode==13000){
//当前设备不支持NFC
}else if(res.errCode==13001){
//系统NFC开关未打开
}else{
//未知错误
}
}
});
//注册发现芯片后处理事件
adapter.onDiscovered(discoverHandlerAuthAndReadM1);
//认证并读取M1卡指定分区处理事件
var discoverHandlerAuthAndReadM1=function(res){
if(res.techs.indexOf('MIFARE Classic') != -1){
GetTagMemery_14443A_MifareClassic(M1Pwd1,M1Pwd2,M1ReadNum);
}else{
//芯片协议不匹配
}
}
//读取14443A MifareClassic内存数据
function GetTagMemery_14443A_MifareClassic(pwd1,pwd2,index){
//读取扇区...
mifare = adapter.getMifareClassic();
mifare.connect({
success: function (ress) {
console.log('MifareClassic已连接',ress);
//认证
var cmd = new Int8Array(12);
//认证指令: 60(KEYA) + 扇区编号 + UID + 12位HEX密钥
if(pwd1!=""){
cmd[0] = parseInt("0x60");
}else{
cmd[0] = parseInt("0x61");
}
cmd[1] = parseInt(parseInt(index)*4, 10);
for (var j = 0; j < uid_arr.length; j++) {
cmd[j + 2] = uid_arr[j];
}
if(pwd1!=""){
cmd[6] = chipTool.hex2int(pwd1.substring(0, 2));
cmd[7] = chipTool.hex2int(pwd1.substring(2, 4));
cmd[8] = chipTool.hex2int(pwd1.substring(4, 6));
cmd[9] = chipTool.hex2int(pwd1.substring(6, 8));
cmd[10] = chipTool.hex2int(pwd1.substring(8, 10));
cmd[11] = chipTool.hex2int(pwd1.substring(10, 12));
}else{
cmd[6] = chipTool.hex2int(pwd2.substring(0, 2));
cmd[7] = chipTool.hex2int(pwd2.substring(2, 4));
cmd[8] = chipTool.hex2int(pwd2.substring(4, 6));
cmd[9] = chipTool.hex2int(pwd2.substring(6, 8));
cmd[10] = chipTool.hex2int(pwd2.substring(8, 10));
cmd[11] = chipTool.hex2int(pwd2.substring(10, 12));
}
var cmdBuffer = cmd.buffer;
//console.log("认证指令为:", cmdBuffer);
//console.log('使用密钥:'+pwd);
mifare.transceive({//发送密钥
data: cmdBuffer,
success: function (res) {
console.log('认证成功, 接收数据如下:', res);
},
fail: function (err) {
//密钥认证失败
mifare.close();
adapter.offDiscovered(discoverHandlerAuthAndReadM1);
adapter.stopDiscovery();
console.log('认证失败', err);
}
});
},
fail: function (err) {
//mifare连接失败
mifare.close();
adapter.offDiscovered(discoverHandlerAuthAndReadM1);
adapter.stopDiscovery();
//console.log('mifare连接失败');
},
complate: function (cp) {
}
})
mifare.isConnected({
success: function (isConnected) {//连接成功
//读取该分区数据
var areaNum=index;
var max=parseInt(areaNum)*4+3;
for (let i = 0; i < 4; i++) {
if(pwd1!=""){
getMifareClassicBlockData(parseInt(areaNum)*4+i,max,pwd1);
}else{
getMifareClassicBlockData(parseInt(areaNum)*4+i,max,pwd2);
}
}
}
});
}
//获取MifareClassic指定区块
function getMifareClassicBlockData(blockNum,maxBlock,pwd){
var cmd = new Int8Array(2);
cmd[0] = parseInt("0x30");
cmd[1] = parseInt(blockNum, 10);
var cmdBuffer = cmd.buffer;
let block_info_tmp = '';
//console.log("读取指令为:", cmdBuffer);
mifare.transceive({
data: cmdBuffer,
success: function (res) {
//console.log('读取数据:', res);
var block_tmp = new Uint8Array(res.data);
for (var j = 0; j < block_tmp.length; j++) {
var tmp = block_tmp[j].toString(16);
if (tmp.length < 2) {
tmp = '0' + tmp;
}
if(j==block_tmp.length-1){
block_info_tmp += tmp;
}else{
block_info_tmp += tmp + ":";
}
}
console.log('第'+blockNum+'块读取数据返回HEX',block_info_tmp);
},
fail: function (err) {
console.log('读取区块'+blockNum+'失败', err);
},
complete:function(){
if(blockNum==maxBlock){
//console.log('M1分区读取结果:',blockInfosM1);
mifare.close();
adapter.offDiscovered(discoverHandlerAuthAndReadM1);
adapter.stopDiscovery();
console.log('关闭mifare连接');
}
}
})
}
到了这里,关于微信小程序读取NFC-MifareClassic1K卡-M1卡详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!