C#写入1K MIFARE卡时如何规避扇区尾块?
解决MIFARE 1K卡写入时避开扇区尾块的问题
我明白你现在的困扰——写入MIFARE 1K卡时不小心写到了扇区尾块,导致卡片损坏。咱们来一步步修复这个问题:
首先得明确核心规则:MIFARE 1K卡分为16个扇区,每个扇区包含4个块,第4块(块号为3、7、11…直到63)是扇区尾块,存储着该扇区的密钥和访问控制规则,绝对不能随意写入。判断这类块的规律很简单:当块号对4取余等于3时,就是扇区尾块(即block % 4 == 3)。
你的现有代码问题
- 循环中没有判断当前块是否为扇区尾块,直接执行了写入操作,导致破坏了卡片的关键配置
- 认证部分写了大量重复的
if语句,冗余且不易维护;实际上每个扇区只需要在进入第一个块时认证一次即可
修改后的代码方案
1. 优化循环逻辑(加入尾块判断+简化认证)
int block = 0; byte[] array = ImageConvert(); string hex = ByteArrayToString(array); Image x = (Bitmap)((new ImageConverter()).ConvertFrom(array)); foreach (byte[] copySlice in array.Slices(16)) { Console.WriteLine(ByteArrayToString(copySlice)); // 简化认证:每个扇区的第一个块(0、4、8...)时执行一次认证 if (block % 4 == 0) { switch(block) { case 0: AuthBlocks.Auth4(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 4: AuthBlocks.Auth8(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 8: AuthBlocks.Auth12(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 12: AuthBlocks.Auth16(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 16: AuthBlocks.Auth20(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 20: AuthBlocks.Auth24(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 24: AuthBlocks.Auth28(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 28: AuthBlocks.Auth32(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 32: AuthBlocks.Auth36(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 36: AuthBlocks.Auth40(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 40: AuthBlocks.Auth44(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 44: AuthBlocks.Auth48(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 48: AuthBlocks.Auth52(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 52: AuthBlocks.Auth56(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 56: AuthBlocks.Auth60(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; case 60: AuthBlocks.Auth60(readerFunctions_, KEYTYPES.ACR122_KEYTYPE_A, 0x00); break; } } // 核心:跳过扇区尾块,只写入普通数据块 if (block % 4 != 3) { writeblocks(block, copySlice); } else { Console.WriteLine($"Skipping sector trailer block: {block}"); } block++; }
2. 优化WriteBlock方法(修复冗余逻辑+增加异常处理)
void writeblocks(int block, byte[] data) { try { // 确保数据长度为16字节,不足则补0 byte[] buff = new byte[16]; Array.Copy(data, buff, Math.Min(data.Length, 16)); myhelper.addTitleToLog(richTextBox1, false, "Update Binary"); mifareClassic_.updateBinary((byte)block, buff, (byte)16); myhelper.addMsgToLog(richTextBox1, $"Update block {block} success"); // 建议去掉每个块都弹MessageBox的操作,改为日志输出,避免干扰流程 // MessageBox.Show("success"); } catch (Exception ex) { // 增加异常处理,方便排查写入失败问题 myhelper.addMsgToLog(richTextBox1, $"Update block {block} failed: {ex.Message}"); MessageBox.Show($"Write block {block} failed: {ex.Message}"); } }
关键说明
- 跳过尾块:通过
block %4 !=3的判断,确保只写入每个扇区的前3个数据块,避免破坏卡片的密钥和控制信息 - 简化认证:用
switch替代大量重复if,同时每个扇区仅在第一个块时认证一次(同一个扇区的所有块共享认证状态,无需重复认证) - 异常处理:给写入方法增加
catch块,方便定位写入失败的原因,避免无提示的错误
额外提醒:扇区尾块只有在你需要修改密钥或访问控制规则时才应该写入,且必须严格遵循MIFARE的格式(6字节密钥A + 4字节访问控制 + 6字节密钥B),否则会导致整个扇区甚至卡片无法访问。
内容的提问来源于stack exchange,提问作者Tolulope
相关产品推荐
相关产品推荐

