You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#写入1K MIFARE卡时如何规避扇区尾块?

解决MIFARE 1K卡写入时避开扇区尾块的问题

我明白你现在的困扰——写入MIFARE 1K卡时不小心写到了扇区尾块,导致卡片损坏。咱们来一步步修复这个问题:

首先得明确核心规则:MIFARE 1K卡分为16个扇区,每个扇区包含4个块,第4块(块号为3、7、11…直到63)是扇区尾块,存储着该扇区的密钥和访问控制规则,绝对不能随意写入。判断这类块的规律很简单:当块号对4取余等于3时,就是扇区尾块(即block % 4 == 3)。

你的现有代码问题

  1. 循环中没有判断当前块是否为扇区尾块,直接执行了写入操作,导致破坏了卡片的关键配置
  2. 认证部分写了大量重复的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:22:50