02.M1实体卡读写技术
目录介绍
- 01.基础概念说明
- 1.1 什么是M1卡
- 1.2 M1卡数据结构
- 1.3 M1扇区密码结构
- 1.4 M1扇区数据块结构
- 1.5 M1卡片操作步骤
- 02.常见思路和做法
- 2.1 M1开发实践思路
- 2.2 M1获取卡类型
- 03.Api调用说明
- 04.遇到的坑分析
- 05.其他问题说明
- 06.技术问题思考&分析
01.基础概念说明
1.1 什么是M1卡
- M1卡是什么东西
- M1芯片,是指菲利浦下属子公司恩智浦出品的芯片缩写,全称为NXP Mifare1系列,常用的有S50及S70两种型号。
- S70与S50主要不同在于卡片的扇区分布和容量不同,M1 S50容量为8KBit,而M1 S70的容量达到了32KBit。
- M1卡卡片介绍
- 以M1 S50卡为案例,M1 S50(以下简称M1)卡片,卡的序列号是全球唯一的,不可修改的32bit数据,M1卡片容量为8KBit。
- 分为:16个扇区,每个扇区4块,每块可存放16个字节byte数据(每个扇区的第4块存放密钥和权限控制字节),可以通过读卡器向卡中不同区域写入相关信息,各扇区独立使用并访问密钥独立,互不干扰。
- 在读取M1卡片数据时,M1卡片只能够按块进行读取,读取扇区数据时,需要循环四次读取该扇区各块数据信息。
- M1卡片访问权限
- M1卡片每个扇区有两个访问密钥:KeyA和KeyB,可以通过权限控制位设定对数据访问及密钥修改时所需要的密钥。
- 具体看:https://blog.csdn.net/ftswsfb/article/details/100183478
1.2 M1卡数据结构
- 扇区和块的含义
- Mifare S50把1K字节的容量分为16个扇区(Sector0-Sector15),每个扇区包括4个数据块(Block0-Block3,我们也将16个扇区的64个块按绝对地址编号为0~63)
- 每个数据块包含16个字节(Byte0-Byte15),4(个数据块)*16(块字节)) * 16(个扇区)= 1024
- M1卡数据存储结构
image
- M1卡数据存储结构说明
- M1卡分为16个扇区,每个扇区4块(块0~3),共64块,按块号编址为0~63。
- 第 0 扇区的块 0(即绝对地址 0 块),它用于存放厂商代码,已经固化,不可更改。注意:第0块不能进行读写操作!
- 每个扇区的块 0、块 1、块 2 为数据块,可用于存贮数据。数据块可作两种应用:第一是用作一般的数据保存,可以进行读、写操作;第二是用作数据值,可以进行初始化值、加值、减值、读值操作。
- 每个扇区的块 3 为控制块,包括了密码 A (6个字节)、存取控制(4个字节)、密码 B(6个字节)。
- 每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。
1.3 M1扇区密码结构
- 每个扇区的块3为控制块,包括了密码A、存取控制、密码B。具体结构如下:
- 密码A(6字节) 存取控制(4字节) 密码B(6字节)。在我们实际开发中用的是密码A
image
- 每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。
- 存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位
image - 例如C1x0中的C代码这是控制位,1代表第一位,0代表是块0的控制位。
- M1卡密码机制。是M1卡最为复杂的地方,在存取控制中每个块都有相应的三个控制位,它们的定义如下
块0: C10 C20 C30 块1: C11 C21 C31 块2: C12 C22 C32 块3: C13 C23 C33
- 一个扇区的三个数据块,我们可以利用密码机制对它们分别进行权限控制。数据块(块0、块1、块2)的存取控制如下:
image - 例如:当块0的存取控制位C10 C20 C30=100时,验证密码A或密码B正确后可读;验证密码B正确后可写;不能进行加值、减值操作。
1.4 M1扇区数据块结构
- 数据块(块0、块1、块2)的存取控制如下
image - KeyA|B 表示密码A或密码B,Never表示任何条件下不能实现
- 例如:当块0的存取控制位C10 C20 C30=1 0 0时,验证密码A或密码B正确后可读;验证密码B正确后可写;不能进行加值、减值操作。
- 控制块(块3)的存取控制与数据块(块0、1、2)不同,它的存取控制如下
image - 例如:当块3的存取控制位C13 C23 C33=1 0 0时,表示:
- 密码A:不可读,验证KEYB正确后可写(更改)。存取控制:不可写,验证KEYA或KEYB正确后可读。密码B:不可读,验证KEYB正确后可写。
1.5 M1卡片操作步骤
- 命令由读写器发出,根据相应区读写条件受数字控制单元的控制。
image
- 第一步:复位应答(发送,有的也叫寻卡)
- 卡上电复位后,通过发送request应答码(ATQA 符合ISO/IEC 14443A),能够回应读写器向天线范围内所有卡发出的request 命令。
- REQA:PCD发出,用于寻找用于类型A PICC的工作场。命令:26H。寻找到卡片,会收到两个字节的应答数据(ATQA)。
- WAKE_UP:PCD发出,使已进入HALT状态的PICC回到READY状态,再次参与防冲突和选择规程。命令:52H
- 第二步:防冲突(SEL1 = 93H,SEL2 = 95H,SEL3 = 97H)
- 在防冲突循环中,读回一张卡的序列号。如果在读写器的工作范围内有几张卡,它们可以通过唯一序列号区分开来,并可选定以进行下一步交易。未被选定的卡转入待命状态,等候新的request命令。
- 命令组成:选择代码SEL(1byte) + 有效位数目NVB(1byte)+ 根据NVB的值,UID Cln的0到40个数据位。只要NVB没有规定40个有效位,若PICC保持在READY状态中,该命令就被称为ANTICOLLISON命令。
- 如果PICC已发送了完整的UID,则它从READY状态转换到ACTIVE状态并在其SAK-响应中指出UID完整。否则,PICC保持在READY状态并且该PCD应该递归串联级别启动一个新的防冲突环。
- 第三步:选择卡片(SEL1 = 93H,SEL2 = 95H,SEL3 = 97H)
- 读写器通过select card命令选定一张卡以进行认证和存储器相关操作。该卡返回选定应答码(ATS= 08h),明确所选卡的卡型。
- 命令组成:选择代码SEL(1byte)+ 有效数目NVB(1byte)+ UID CLn 40个数据位(NVB = 70H)+ CRC_A
- 第四步:三轮认证
- 选卡后,读写器指定后续读写的存储器位置,并用相应密钥进行三轮认证。认证成功后,所有的存储器操作都是加密的。
- 第五步:业务操作(存储器操作)
- 密钥修改;访问权限修改;读写块数据
- 第六步:停止
- PCD发出HALT命令,使PICC进入HALT状态。
- 附:防冲突技术
- 正常情况下,读卡器在某一时刻只能对磁场中的一张射频卡进行读写操作,但是当多张卡片同时进入读卡器的射频场时,读卡器需要选出唯一一张卡片进行读写操作,这就是防冲突。
- 常见的非接触式卡片中放冲突机制主要有以下三种:面向比特的放冲突机制(ISO 14443a使用)、面向时隙的防冲突机制(ISO 14443b使用)、位与时隙相结合的放冲突机制(ISO 14693使用)。
1.6 M1卡运作机理
- M1卡运作的机理流程如下:
- 连接读写器 → 寻卡 → 识别卡(获取卡序列号) → 从多卡中选一张卡 → 向卡中缓冲区装载密码 → 验证密码 → 进行读写 → 关闭连接
- 如果概括来说的话,主要也就五部分:
- 开关连接、寻卡、验证密码、读取、关闭(归位)。
- 基本操作规则。如下所示:
- (1)程序开始,调用rf_init函数初始化串口。
- (2)寻卡,调用rf_card;
- (3)对单个扇区操作,顺次执行A~D;A、选定要操作的扇区;B、装载密码,调用rf_load_key;C、验证密码,调用rf_authentication;D、进行操作,包括读写及值操作。E、调用rf_halt。
- (4)关闭串口,调用rf_exit。程序正常退出或因错误退出之前,要使用函数;否则再次执行初始化串口时将出错。
02.常见思路和做法
2.1 M1开发实践思路
- M1开发实践思路步骤如下
- 第一步:获取卡类型。程序开始,开始初始化串口。然后开始寻卡操作。
- 第二步:获取卡号。不可更改的序列号,保证了每张卡的唯一性。
- 第三步:M1扇区读写。读写卡操作分为两个步骤:密码校验、读写卡。只有对当前要读写的块数据所在的扇区进行密码校验之后才能进行接下来的读写操作。
- 第四步:M1重置操作
2.2 M1获取卡类型
2.3 获取M1卡号
2.4 M1扇区读写
2.5 M1重置操作
2.6 M1卡修改密码
03.Api调用说明
04.遇到的坑分析
05.其他问题说明
06.技术问题思考&分析
其他参考博客
NFC M1卡读写
- https://www.jianshu.com/p/4f0c9012bd17
M1卡介绍
- https://blog.csdn.net/lpb914/article/details/123655450
Mifare 1卡(M1卡、IC卡)读写操作及工作原理整理
- https://blog.csdn.net/qq_32348883/article/details/126603790
卡的信息。余额是:111.04元
D Card UnionImpl : M1卡类型
D Card UnionImpl : M1 卡号B1F9705C
D Card M1 flipCardNum : 5c70f9b1 , 5c70f9b1 , 天安 M1卡秘钥 99a1ccc6bb40a8339e7c65445b6c7b09b6214065d3e023439b052d32f12c7d8c
D Card M1 cardKeyArray = F2 3E 98 89 D0 32 73 6B E5 1A 5D 86 6B CE EF 43 , taKeys f23e9889d032736be51a5d866bceef43
D 读数据扇区 24 , 密钥 F2 3E 98 89 D0 32 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 25 , 密钥 F2 3E 98 89 D0 32 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 26 , 密钥 F2 3E 98 89 D0 32 , 卡号 b1f9705c , 验证结果true
D Card M1 扇区6密钥认证成功:7768340000000000000000000000000000000000000000000000000000000000000000
D 读数据扇区 28 , 密钥 73 6B E5 1A 5D 86 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 29 , 密钥 73 6B E5 1A 5D 86 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 30 , 密钥 73 6B E5 1A 5D 86 , 卡号 b1f9705c , 验证结果true
D Card M1 扇区7密钥认证成功:cee4babab2e2cad4346d3100000000000000000000000093c6d0a2fbf633f62d69537866c2fb3e4b29ba4f
D 读数据扇区 32 , 密钥 F2 73 6B CE EF 43 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 33 , 密钥 F2 73 6B CE EF 43 , 卡号 b1f9705c , 验证结果true
D Card M1 扇区8密钥认证成功:0000000000000000000000000000000024040800000000020000010c00000027
D Card M1 cardData = 7768340000000000000000000000000000000000000000000000000000000000000000cee4babab2e2cad4346d3100000000000000000000000093c6d0a2fbf633f62d69537866c2fb3e4b29ba4f0000000000000000000000000000000024040800000000020000010c00000027
D Card M1 nfcResult = NfcResult{cardType=0, result=1, cardId='5c70f9b1', resultMsg='解卡成功', studentId='wh4', userName='', sign='66c2fb3e4b29ba4f0000000000000000', date='000000', crc32Data=0, totalMoney=9684688, cardDailyNum=0, version=0, totalCount=0, csTotalMoney=761877368, stTotalMoney=-67750922}
D nfcResult = NfcResult{cardType=0, result=1, cardId='5c70f9b1', resultMsg='解卡成功', studentId='wh4', userName='', sign='66c2fb3e4b29ba4f0000000000000000', date='000000', crc32Data=0, totalMoney=9684688, cardDailyNum=0, version=0, totalCount=0, csTotalMoney=761877368, stTotalMoney=-67750922}
- 支付1元后的信息。余额是:110.04元
D Card UnionImpl : M1卡类型
D Card UnionImpl : M1 卡号B1F9705C
D Card M1 flipCardNum : 5c70f9b1 , 5c70f9b1 , 天安 M1卡秘钥 99a1ccc6bb40a8339e7c65445b6c7b09b6214065d3e023439b052d32f12c7d8c
D Card M1 cardKeyArray = F2 3E 98 89 D0 32 73 6B E5 1A 5D 86 6B CE EF 43 , taKeys f23e9889d032736be51a5d866bceef43
D 读数据扇区 24 , 密钥 F2 3E 98 89 D0 32 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 25 , 密钥 F2 3E 98 89 D0 32 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 26 , 密钥 F2 3E 98 89 D0 32 , 卡号 b1f9705c , 验证结果true
D Card M1 扇区6密钥认证成功:7768340000000000000000000000000000000000000000000000000000000000000000
D 读数据扇区 28 , 密钥 73 6B E5 1A 5D 86 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 29 , 密钥 73 6B E5 1A 5D 86 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 30 , 密钥 73 6B E5 1A 5D 86 , 卡号 b1f9705c , 验证结果true
D Card M1 扇区7密钥认证成功:cee4babab2e2cad4346d3100000000000000000000000093c6d0a2fbf633f62d69537866c2fb3e4b29ba4f
D 读数据扇区 32 , 密钥 F2 73 6B CE EF 43 , 卡号 b1f9705c , 验证结果true
D 读数据扇区 33 , 密钥 F2 73 6B CE EF 43 , 卡号 b1f9705c , 验证结果true
D Card M1 扇区8密钥认证成功:0000000000000000000000000000000024041100000000010000010d0000003c
D Card M1 cardData = 7768340000000000000000000000000000000000000000000000000000000000000000cee4babab2e2cad4346d3100000000000000000000000093c6d0a2fbf633f62d69537866c2fb3e4b29ba4f0000000000000000000000000000000024041100000000010000010d0000003c
D Card M1 nfcResult = NfcResult{cardType=0, result=1, cardId='5c70f9b1', resultMsg='解卡成功', studentId='wh4', userName='', sign='66c2fb3e4b29ba4f0000000000000000', date='000000', crc32Data=0, totalMoney=9684688, cardDailyNum=0, version=0, totalCount=0, csTotalMoney=761877368, stTotalMoney=-67750922}
D nfcResult = NfcResult{cardType=0, result=1, cardId='5c70f9b1', resultMsg='解卡成功', studentId='wh4', userName='', sign='66c2fb3e4b29ba4f0000000000000000', date='000000', crc32Data=0, totalMoney=9684688, cardDailyNum=0, version=0, totalCount=0, csTotalMoney=761877368, stTotalMoney=-67750922}