M1 卡 FM1702sl读写
2017年03月06日 15:28:42 阅读数:894 标签: M1RFIDIC读写IC密码修改 更多
最近开始研究了FM1702sl IC卡,觉得很有必要解决一些开发中存在的问题。
一、 M1射频卡与读写器的通讯
相信大家对这样的读卡流程不陌生。
二、 存储结构
1、 M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,存贮结构如下图所示:
|
||||
块0 |
|
数据块 |
0 |
|
扇区0 |
块1 |
数据块 |
1 |
|
块2 |
数据块 |
2 |
||
块3 |
密码A 存取控制 密码B |
控制块 |
3 |
|
|
块0 |
数据块 |
4 |
|
扇区1 |
块1 |
数据块 |
5 |
|
块2 |
数据块 |
6 |
||
块3 |
密码A 存取控制 密码B |
控制块 |
7 |
|
∶ ∶ ∶ |
||||
|
0 |
数据块 |
60 |
|
扇区15 |
1 |
数据块 |
61 |
|
2 |
数据块 |
62 |
||
3 |
密码A 存取控制 密码B |
控制块 |
63 |
2、 第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
3、 每个扇区的块0、块1、块2为数据块,可用于存贮数据。
数据块可作两种应用:
★ 用作一般的数据保存,可以进行读、写操作。
★ 用作数据值,可以进行初始化值、加值、减值、读值操作。
4、 每个扇区的块3为控制块,包括了密码A、存取控制、密码B。具体结构如下:
密码A(6字节) 存取控制(4字节) 密码B(6字节)
5、 每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位,定义如下:
块0: C10 C20 C30
块1: C11 C21 C31
块2: C12 C22 C32
块3: C13 C23 C33
三个控制位以正和反两种形式存在于存取控制字节中,决定了该块的访问权限(如
进行减值操作必须验证KEY A,进行加值操作必须验证KEY B,等等)。三个控制
位在存取控制字节中的位置,以块0为例:
对块0的控制:
bit 7 6 5 4 3 2 1 0
字节6 |
C20_b |
C10_b |
||||||
字节7 |
C10 |
C30_b |
||||||
字节8 |
C30 |
C20 |
||||||
字节9 |
( 注: C10_b表示C10取反)
存取控制(4字节,其中字节9为备用字节)结构如下所示:
bit 7 6 5 4 3 2 1 0
字节6 |
C23_b |
C22_b |
C21_b |
C20_b |
C13_b |
C12_b |
C11_b |
C10_b |
字节7 |
C13 |
C12 |
C11 |
C10 |
C33_b |
C32_b |
C31_b |
C30_b |
字节8 |
C33 |
C32 |
C31 |
C30 |
C23 |
C22 |
C21 |
C20 |
字节9 |
( 注: _b表示取反)
6、数据块(块0、块1、块2)的存取控制如下:
控制位(X=0.1.2)
|
访 问 条 件 (对数据块 0、1、2) |
|||||
C1X |
C2X |
C3X |
Read |
Write |
Increment |
Decrement, transfer, Restore |
0 |
0 |
0 |
KeyA|B |
KeyA|B |
KeyA|B |
KeyA|B |
0 |
1 |
0 |
KeyA|B |
Never |
Never |
Never |
1 |
0 |
0 |
KeyA|B |
KeyB |
Never |
Never |
1 |
1 |
0 |
KeyA|B |
KeyB |
KeyB |
KeyA|B |
0 |
0 |
1 |
KeyA|B |
Never |
Never |
KeyA|B |
0 |
1 |
1 |
KeyB |
KeyB |
Never |
Never |
1 |
0 |
1 |
KeyB |
Never |
Never |
Never |
1 |
1 |
1 |
Never |
Never |
Never |
Never |
(KeyA|B 表示密码A或密码B,Never表示任何条件下不能实现)
例如:当块0的存取控制位C10 C20 C30=1 0 0时,验证密码A或密码B正确后可读;
验证密码B正确后可写;不能进行加值、减值操作。
7、控制块块3的存取控制与数据块(块0、1、2)不同,它的存取控制如下:
密码A |
存取控制 |
密码B |
||||||
C13 |
C23 |
C33 |
Read |
Write |
Read |
Write |
Read |
Write |
0 |
0 |
0 |
Never |
KeyA|B |
KeyA|B |
Never |
KeyA|B |
KeyA|B |
0 |
1 |
0 |
Never |
Never |
KeyA|B |
Never |
KeyA|B |
Never |
1 |
0 |
0 |
Never |
KeyB |
KeyA|B |
Never |
Never |
KeyB |
1 |
1 |
0 |
Never |
Never |
KeyA|B |
Never |
Never |
Never |
0 |
0 |
1 |
Never |
KeyA|B |
KeyA|B |
KeyA|B |
KeyA|B |
KeyA|B |
0 |
1 |
1 |
Never |
KeyB |
KeyA|B |
KeyB |
Never |
KeyB |
1 |
0 |
1 |
Never |
Never |
KeyA|B |
KeyB |
Never |
Never |
1 |
1 |
1 |
Never |
Never |
KeyA|B |
Never |
Never |
Never |
例如:当块3的存取控制位C13 C23 C33=1 0 0时,表示:
密码A:不可读,验证KEYA或KEYB正确后,可写(更改)。
存取控制:验证KEYA或KEYB正确后,可读、可写。
密码B:验证KEYA或KEYB正确后,可读、可写。
三、 工作原理
卡片的电气部分只由一个天线和ASIC组成。
天线:卡片的天线是只有几组绕线的线圈,很适于封装到IS0卡片中。
ASIC:卡片的ASIC由一个高速(106KB波特率)的RF接口,一个控制单元和一个
8K位EEPROM组成。
工作原理:读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。
我在stm32上进行了一些测试,主要源码如下
int main(void)
{
uchar i;
unsigned char status, try;
unsigned char buf[16], DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE};
unsigned char buffer[16]={"123fddd"};
//System_Setup();
NVIC_Configuration();
GPIO_ini();
InitializeSystem( );
USART_Configuration();
LED_Configuration();
RS232_REC_Flag=0;
while (1)
{
try = 4;
while(--try)
{
status = Request(RF_CMD_REQUEST_ALL); //寻卡
if(status != FM1702_OK) continue;
status = AntiColl(); //冲突检测
if(status != FM1702_OK) continue;
status=Select_Card(); //选卡
if(status != FM1702_OK) continue;
status = Load_keyE2_CPY(DefaultKey); //加载密码
if(status != TRUE) continue;
status = Authentication(UID, 4, RF_CMD_AUTH_LB); //验证1扇区keyA
if(status != FM1702_OK) continue;
if(RS232_REC_Flag==1)
{
status=MIF_Write(RS232_buff,19); //写卡,将buffer[0]-buffer[15]写入1扇区0块
memsets(RS232_buff);
delay(100);
RS232_rec_counter = 0;//发送完将接收计数器清零
}else{
status=MIF_READ(buf,19); //读卡,读取1扇区0块数据到buffer[0]-buffer[15]
}
if(status == FM1702_OK)
{
if(RS232_REC_Flag==1)
{
//RS232_Send_Data("write:",6);
RS232_REC_Flag = 0;
}
else
{
//RS232_Send_Data("read:",5);
delay(100);
RS232_Send_Data(buf,16);
}
LED_ON;
delay(10000);
}
}
if(try == 0) LED_OFF;
}
}
串口得到的数据如下
这里需要解释地方就是这些数据,00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FE 为密码区的数据,前六位为keyA,之所以为00是因为他对用户不是透明的,不管你怎么修改keyA密码,但是keyB不是。所以我们看到了B的密码为 FF FF FF FF FF FE 。我们通过串口发送数据到读卡器修改这个扇区的密码,也就是发送区的数据。我们将密码B改为了FF FF FF FF FF FE ,keyA为 00 00 00 00 00 00。实际上keyA key B初始密码都为FF FF FF FF FF FF 当然因卡而定。
这是我觉得最为重要的一个地方。
有一个问题答疑的地方如下:
1 问:多张卡在读卡器上的时候,我读取了其中一张卡的时候,然后要执行halt操作才可以其他的卡
答:这是可以的
2 问:读到一张卡的时候,在没有执行halt操作之前,如果再操作这张卡,且在同一扇区,那么直接执行读操作时就不用再重复执行防冲突选卡操作
答:可以的
3 问:至于要换成其他的扇区时候
答 : 读是可以的,写要重新寻卡等一系列操作。
有什么疑问可以咨询我:QQ:978508554