获取 mifare 卡序列号不正确

Posted

技术标签:

【中文标题】获取 mifare 卡序列号不正确【英文标题】:Get mifare card serial number is incorrect 【发布时间】:2015-11-08 16:56:13 【问题描述】:

使用我使用的读卡器,获取MIFARE卡序列号的协议如下:

Mifare 防碰撞,0x0202: 功能卡防撞 格式      aa bb 05 00 00 00 02 02 00 回复aa bb 0a 00 52 51 02 02 00 46 ff a6 b8 a4

其中46 ff a6 b8是上述响应中的卡序列号。

我在 C# 中实现这个协议如下:

private SerialPort _serialPort = new SerialPort();
private string _receivedData = null;

public MifareCardReader(string comPort, int baudRate)

    _serialPort = new SerialPort();
    _serialPort.PortName = comPort;
    _serialPort.BaudRate = baudRate;
    _serialPort.DataBits = 8;
    _serialPort.Parity = Parity.None;
    _serialPort.StopBits = StopBits.One;
    _serialPort.Handshake = Handshake.None;
    _serialPort.Open();   

    // Add event
    _serialPort.DataReceived += SerialPort_DataReceived;     


public string MifareAnticollision()

    if (_serialPort != null && _serialPort.IsOpen)
    
        string message = "AABB050000000202000D";
        byte[] data = StringToByteArray(message);
        _serialPort.Write(data, 0, data.Length);
    


private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)

    _receivedData += _serialPort.ReadExisting();
    byte[] data = Encoding.ASCII.GetBytes(receivedData);
    if (data.Length >= 9)
    
        if (data[8] == 0) // OK
        
            // Response data is complete
            if (data.Length == 14)
            
                StringBuilder hex = new StringBuilder(8);
                hex.AppendFormat("0:X2", data[9]);
                hex.AppendFormat("0:X2", data[10]);
                hex.AppendFormat("0:X2", data[11]);
                hex.AppendFormat("0:X2", data[12]);

                string cardID = hex.ToString();
                _receivedData = string.Empty;
            
        
        else // fail
        
            _receivedData = string.Empty;
        
    

我用 3 种不同的 MIFARE 卡对此进行了测试,但是,输出不是我所期望的:

卡 1:收到:3F463F3F,预期:974682D6 卡 2:收到:3F450B3F,预期:EA450B91 卡 3:收到:070D3F3F,预期:070DEBD6

我需要更改什么才能获得正确的输出?

【问题讨论】:

但是你的问题是什么? 我完全按照协议做了,但没有得到正确的卡序列号。我不知道为什么。我的算法错误或协议丢失??? 好的,所以你有错误的输出,只需给我 3 个输入示例作为十六进制值和你想要得到的输出,我会为你修复它:) Card3: 070D3F3F 是错误的输出?还是输入? 你通过串口说的是什么? 如果是this读者。为什么不使用“Mifare S50 select a card (Request + anticollision + select) 0x0200”组合命令?我对这个特定的读者没有经验,但通常REQA(在你的情况下是命令 0x0201)应该在 CL1(在你的情况下是命令 0x0202)之前。 【参考方案1】:

您遇到的问题似乎是将值高于0x7F 的字节替换为0x3F(问号(“?”)字符)。 IE。只有 7 位值正确显示,第 8 位设置的值变成“?” (0x3F)。例如。对于卡 1,974682D6 被“接收”为 3F463F3F,因为 0x970x820xD6 设置了它们的第 8 位。

这个问题的根源是你正在使用ReadExisting()方法从串口读取一个字符串值。默认情况下,ReadExisting() 从串行端口读取字节,使用 ASCII 编码 (System.Text.ASCIIEncoding) 转换它们,并返回结果字符串。然后获取该字符串并将其转换回字节数组(再次使用 ASCII 编码)。

有问题的步骤是使用System.Text.ASCIIEncoding/Encoding.ASCII 的转换。 documentation 说:

由于 ASCII 是 7 位编码,ASCII 字符限制为最低 128 个 Unicode 字符,从 U+0000 到 U+007F。 [...] 超出该范围的字符在执行编码操作之前被替换为问号 (?)

因此,您应该使用Read()ReadByte() 方法将字节直接读入字节数组。例如。与

byte[] buffer = new byte[_serialPort.ReadBufferSize];
int bytesRead = _serialPort.Read(buffer, 0, buffer.Length);

【讨论】:

以上是关于获取 mifare 卡序列号不正确的主要内容,如果未能解决你的问题,请参考以下文章

uID卡和fuID的区别

NFC的mifare卡与ntag具体区别

Android 获取sim卡序列号

Mifare卡版获取方法

mifare教程 用MifareClassic工具模拟加密门禁教程

Mifare卡安全