M1卡 不能使用KeyB进行读写的问题

本文详细解析了M1卡的权限配置问题,包括控制字FF078069和08778F00的具体含义及操作权限。阐述了在特定配置下使用KeyB进行认证的限制,并提供了修改方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提知识:

#M1卡控制位对应操作权限:

M1卡即S50卡,存取控制(4字节,其中字节9为备用字节)结构如下所示:

 数据块(块0、块1、块2)的存取控制如下:

 

  控制位(X=0..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正确后可写;不能进行加值、减值操作。

 

    控制块块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正确后,可读、可写。

一、现象

对白卡进行操作,KeyA和KeyB都是FF FF FF FF FF FF ,控制字是FF 07 80 69。解析这组控制字的话,如下:

FF 07 80 69

         bit  7    6     5       4     3      2      1      0

字节6

1

1

1

1

1

1

1

1

字节7

0

0

0

0

0

1

1

1

字节8

1

0

0

0

0

0

0

0

字节9

0

1

1

0

1

0

0

1

C10 C20 C30 :0 0 0

C11 C21 C31 :0 0 0

C12 C22 C32 :0 0 0

C13 C23 C33 :0 0 1

 

分析操作权限可知,此时使用KeyA和KeyB,都应是可以对各块进行操作的。但实际情况是,部分卡使用KeyA可以正常读写,使用KeyB则不行。

二、原因

根据M1卡的规则,KeyA一直是不可读的,但KeyB是可以配置的,在FF 07 80 69这个配置下,KeyB是可见的。如果KeyB可读则不可以使用其进行认证,也就不能进行读写,如手册中所说:

而为什么只有部分卡不行,应该是NXP原厂是有此限制,另外一些替代卡不一定有。

三、处理

将控制字修改为08 77 8F 00,如下:

08 77 8F 00

         bit  7    6     5       4     3      2      1      0

字节6

0

0

0

0

1

0

0

0

字节7

0

1

1

1

0

1

1

1

字节8

1

0

0

0

1

1

1

1

字节9

0

0

0

0

0

0

0

0

C10 C20 C30 :1 1 0

C11 C21 C31 :1 1 0

C12 C22 C32 :1 1 0

C13 C23 C33 :0 1 1

为控制真值表中红字部分,此后KeyB不可见,block3数据如下:

00000000000008778F00000000000000

此后可使用KeyB进行读写。

 

参考:

https://blog.youkuaiyun.com/robinson_911/article/details/12783897

《Mifare Classic 1K-S50.pdf》

<think>我们正在讨论Mifare Classic M1(简称M1)的扇区尾块操作。用户的问题集中在三个方面: 1. 修改扇区尾块密钥的方法 2. 认证失败的可能原因 3. 扇区尾块控制位的解析 根据引用[1][2],我们知道: - M116个扇区,每个扇区4个块(块0~块3),每个块16字节。 - 扇区尾块(即块3)存储了该扇区的密钥A(6字节)、访问控制位(4字节)和密钥B(6字节)。 - 要修改尾块中的密钥,必须通过认证(使用当前有效的密钥)并正确设置访问控制位。 下面分别详细解答: ### 一、修改扇区尾块密钥的方法 修改密钥本质上是修改尾块的数据。由于尾块包含密钥和访问控制位,修改时必须非常谨慎。步骤如下: 1. **认证当前扇区** 使用当前有效的密钥(可能是默认密钥`FFFFFFFFFFFF`或自定义密钥)对目标扇区进行认证: ```c MFRC522::StatusCode status = mfrc522.PCD_Authenticate( MFRC522::PICC_CMD_MF_AUTH_KEY_A, // 或使用_KEY_B blockAddr, // 尾块地址(扇区号*4+3) &currentKey, // 当前密钥 &(mfrc522.uid) ); ``` 2. **准备新尾块数据** 尾块16字节结构:`[新密钥A(6B)][访问控制位(4B)][新密钥B(6B)]`。 例如,要将密钥A改为`A0A1A2A3A4A5`,密钥B改为`B0B1B2B3B4B5`,保留原访问控制位(假设为`FF078069`): ```c byte newTrailerBlock[16] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, // 新密钥A 0xFF, 0x07, 0x80, 0x69, // 访问控制位(保持不变) 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5 // 新密钥B }; ``` 3. **入尾块** **注意:入尾块前必须确保访问控制位允许入!** 使用`MIFARE_Write`函数入: ```c status = mfrc522.MIFARE_Write(blockAddr, newTrailerBlock, 16); if (status != MFRC522::STATUS_OK) { // 处理错误 } ``` #### 关键注意事项 - **访问控制位权限**:尾块的访问控制位本身控制着密钥和访问控制位的修改权限。如果当前控制位不允许用该密钥修改,则操作会失败[^2]。 - **保留字节**:访问控制位中间的4个字节中,实际只使用前3个字节(共24位),最后一个字节(第9字节)通常作为用户数据或保留,但某些可能要求其为特定值(如`0x69`)[^2]。 - **密钥格式**:密钥必须为6字节的十六进制值。 ### 二、认证失败的可能原因 引用[2][4]指出,认证失败可能由以下原因引起: 1. **密钥错误** - 使用的密钥与扇区尾块中存储的密钥不匹配。 - 默认密钥已被修改(不再是`FFFFFFFFFFFF`或`000000000000`)。 2. **访问控制位配置错误** - 控制位禁止了当前密钥的认证权限(例如,配置为只能用密钥B认证,但尝试用密钥A认证)[^2]。 3. **通信错误** - 片与读器距离过远或存在干扰。 - 片移动导致通信中断(返回`STATUS_TIMEOUT`)[^4]。 4. **片类型不匹配** - 片不是Mifare Classic 1K(M1。 5. **未选择片** - 在认证前未成功选择片(`PICC_ReadCardSerial`失败)。 6. **密钥格式错误** - 密钥长度不是6字节。 ### 三、扇区尾块控制位解析 尾块的第6~9字节为访问控制位(共4字节),实际有效位为前3字节(24位),按**每块4位**的规则控制该扇区4个块的权限。控制位结构如下(以字节序排列): ``` 字节6: [C10, C20, C30] // 块0的权限 字节7: [C11, C21, C31] // 块1的权限 字节8: [C12, C22, C32] // 块2的权限 字节9: [C13, C23, C33] // 块3(尾块)的权限 ``` > 注意:每个块的权限由3个控制位(C1, C2, C3)决定,共4种组合方式(0~3)。 #### 权限规则表 | C1 C2 C3 | 密钥A权限(读//增减) | 密钥B权限 | |----------|------------------------|----------| | 0 0 0 | 禁止所有操作 | 禁止 | | 0 1 0 | 认证后只读 | 认证后可 | | 1 0 0 | 认证后可读/ | 认证后可读 | | 1 1 0 | 认证后可读 | 认证后可 | | 0 0 1 | 禁止所有操作 | 禁止 | | 0 1 1 | 认证后只读 | 认证后增减 | | 1 0 1 | 认证后可读/ | 认证后增减 | | 1 1 1 | 认证后只读 | 认证后增减 | #### 尾块(块3)的特殊控制 尾块的权限由`C13, C23, C33`控制,其组合决定密钥和控制位的修改方式: | C13 C23 C33 | 密钥A可读 | 密钥A可 | 访问位可 | 密钥B可读 | 密钥B可 | |-------------|-----------|-----------|------------|-----------|-----------| | 0 0 0 | Never | Never | Never | Never | Never | | 0 1 0 | KeyA | Never | Never | KeyA | Never | | 1 0 0 | KeyB | Never | Never | Never | Never | | 1 1 0 | KeyA|B | Never | Never | KeyA|B | Never | | 0 0 1 | Never | KeyA | KeyA | Never | KeyA | | 0 1 1 | KeyB | Never | Never | Never | Never | | 1 0 1 | KeyB | KeyB | KeyB | Never | KeyB | | 1 1 1 | KeyA|B | KeyB | KeyB | KeyA|B | KeyB | > 重要提示:若错误设置控制位(如设为`000`),将导致整个扇区永久锁定! ### 总结操作建议 1. **修改密钥前务必备份原控制位**,避免意外锁定扇区。 2. 使用默认密钥时,优先尝试`FFFFFFFFFFFF`和`000000000000`。 3. 认证失败时,检查: - 片类型(是否为M1) - 密钥正确性 - 控制位配置(是否允许当前操作) --- §§相关问题§§ 1. 如何恢复被错误控制位锁定的M1扇区? 2. M1控制位设置的最佳实践是什么? 3. 如何批量修改多个扇区的密钥?</think>### Mifare Classic M1扇区尾块操作详解 #### 一、修改扇区尾块密钥的方法 修改扇区尾块密钥需要经过**认证→构造新数据→入**三个关键步骤: 1. **认证当前扇区**(使用原密钥) ```c // 使用密钥A认证(假设原密钥为FFFFFFFFFFFF) byte keyA[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; byte sector = 1; // 目标扇区 byte blockAddr = sector * 4 + 3; // 尾块地址 MFRC522::StatusCode status = mfrc522.PCD_Authenticate( MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockAddr, &keyA, &(mfrc522.uid) ); ``` 2. **构造新尾块数据** ```c // 新尾块数据结构:[6B新密钥A] + [4B访问位] + [6B新密钥B] byte newKeyA[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; // 新密钥A byte newKeyB[6] = {0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5}; // 新密钥B byte accessBits[4] = {0xFF, 0x07, 0x80, 0x69}; // 访问控制位(保持不变) byte newTrailer[16]; memcpy(newTrailer, newKeyA, 6); // 0-5字节: 密钥A memcpy(newTrailer+6, accessBits, 4); // 6-9字节: 访问位 memcpy(newTrailer+10, newKeyB, 6); // 10-15字节: 密钥B ``` 3. **入新密钥数据** ```c status = mfrc522.MIFARE_Write(blockAddr, newTrailer, 16); if (status == MFRC522::STATUS_OK) { Serial.println("密钥修改成功!"); } else { Serial.print("入失败: "); Serial.println(mfrc522.GetStatusCodeName(status)); } ``` > **关键注意事项**: > 1. 修改前必须确认当前访问控制位允许密钥入[^2] > 2. 保留访问控制位第9字节为`0x69`(某些片要求) > 3. 修改后立即用新密钥测试认证 > 4. **错误操作可能导致扇区永久锁定!** #### 二、认证失败的常见原因 根据引用[2][4],认证失败主要涉及以下方面: | 原因类型 | 具体表现 | 解决方案 | |---------|---------|---------| | **密钥问题** | 密钥错误/被修改 | 1. 尝试默认密钥`FFFFFFFFFFFF`或`000000000000`<br>2. 使用密钥嗅探工具恢复 | | **访问控制位** | 权限配置禁止操作 | 1. 检查控制位是否允许当前操作<br>2. 尝试密钥B认证(如`C1=0, C2=0, C3=1`) | | **片状态** | 片被锁定/损坏 | 1. 测试其他扇区是否可读<br>2. 更换片测试 | | **硬件问题** | 通信超时(`STATUS_TIMEOUT`) | 1. 调整读距离(2-5cm)<br>2. 检查天线连接<br>3. 排除电磁干扰源 | | **操作流程** | 未选择片/时序错误 | 1. 确认执行`PICC_ReadCardSerial()`<br>2. 添加延时`delay(50)` | > 特殊案例:当控制位设置为`000`时,扇区将被**永久锁定**,任何密钥都无法认证[^2]。 #### 三、扇区尾块控制位解析 尾块的第6-9字节为访问控制位(实际有效位24位),控制结构如下: **1. 控制位分布**(每块3位) ``` 字节6: [块0: C10, C20, C30] 字节7: [块1: C11, C21, C31] 字节8: [块2: C12, C22, C32] 字节9: [尾块: C13, C23, C33] + 保留位 ``` **2. 尾块权限解析**(C13 C23 C33组合) | 二进制 | 密钥A读取 | 密钥A修改 | 控制位修改 | 密钥B读取 | 密钥B修改 | |-------|----------|----------|-----------|----------|----------| | `000` | ❌禁止 | ❌禁止 | ❌禁止 | ❌禁止 | ❌禁止 | | `010` | ✅允许 | ❌禁止 | ❌禁止 | ✅允许 | ❌禁止 | | `100` | ✅允许 | ❌禁止 | ❌禁止 | ❌禁止 | ❌禁止 | | `110` | ✅允许 | ❌禁止 | ❌禁止 | ✅允许 | ❌禁止 | | `001` | ❌禁止 | ✅需密钥A | ✅需密钥A | ❌禁止 | ✅需密钥A | | `101` | ✅允许 | ✅需密钥B | ✅需密钥B | ❌禁止 | ✅需密钥B | | `011` | ✅允许 | ❌禁止 | ❌禁止 | ❌禁止 | ❌禁止 | | `111` | ✅允许 | ✅需密钥B | ✅需密钥B | ✅允许 | ✅需密钥B | **3. 默认控制位解析**(`FF 07 80`): - 十六进制:`0xFF, 0x07, 0x80` → 二进制:`11111111 00000111 10000000` - 对应权限: - 块0-2:`C1x=1, C2x=1, C3x=1` → 可读//增值 - 尾块:`C13=1, C23=1, C33=0` → 密钥A可读,密钥B可读,**禁止修改** > **重要提示**:修改控制位时需确保至少保留一个有效操作密钥,否则会导致扇区永久锁定[^2]。 ### 操作安全建议 1. 修改密钥前务必**备份原控制位** 2. 首次操作使用测试(非重要数据) 3. 使用`0xFFFFFFFFFFFF`和`0x000000000000`双重测试 4. 修改后立即验证新密钥有效性 ```c // 验证新密钥 status = mfrc522.PCD_Authenticate( MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockAddr, &newKeyA, // 新密钥 &(mfrc522.uid) ); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值