我有一个 NFC 读卡器和 MIFARE Classic 1K 卡。我有一个 Visual C# winforms 项目。现在我能够连接到读卡器并检测卡并获取它的 UUID。我面临的问题是在写入和读取数据时。我在互联网上搜索了很多,找到了一些解决方案,甚至测试了 SDK 提供的演示代码......没有任何工作。
让我描述一下我用于编写、验证块、发送 APDU 和读取块的工作流程和代码。
以下是将数据写入块 5 的代码。
String tmpStr = Text;
int indx;
if (authenticateBlock(Block))
{
ClearBuffers();
SendBuff[0] = 0xFF; // CLA
SendBuff[1] = 0xD6; // INS
SendBuff[2] = 0x00; // P1
SendBuff[3] = (byte)int.Parse(Block); // P2 : Starting Block No.
SendBuff[4] = (byte)int.Parse("16"); // P3 : Data length
SendBuff[5] = 0xFF;
SendBuff[6] = 0xFF;
SendBuff[7] = 0xFF;
SendBuff[8] = 0xFF;
SendBuff[9] = 0xFF;
SendBuff[10] = 0xFF;
for (indx = 0; indx <= (tmpStr).Length - 1; indx++)
{
SendBuff[indx + 5] = (byte)tmpStr[indx];
}
SendLen = SendBuff[4] + 5;
RecvLen = 0x02;
retCode = SendAPDUandDisplay(2);
if (retCode != Card.SCARD_S_SUCCESS)
{
MessageBox.Show("fail write");
}
else
{
MessageBox.Show("write success");
}
}
else
{
MessageBox.Show("FailAuthentication");
}
CloseCardConnection();
SendAPDUandDisplay 函数如下
private int SendAPDUandDisplay(int reqType)
{
int indx;
string tmpStr = "";
pioSendRequest.dwProtocol = Aprotocol;
pioSendRequest.cbPciLength = 8;
//Display Apdu In
for (indx = 0; indx <= SendLen - 1; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuff[indx]);
}
retCode = Card.SCardTransmit(hCard, ref pioSendRequest, ref SendBuff[0],
SendLen, ref pioSendRequest, ref RecvBuff[0], ref RecvLen);
if (retCode != Card.SCARD_S_SUCCESS)
{
return retCode;
}
else
{
try
{
tmpStr = "";
switch (reqType)
{
case 0:
for (indx = (RecvLen - 2); indx <= (RecvLen - 1); indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
if ((tmpStr).Trim() != "90 00")
{
//MessageBox.Show("Return bytes are not acceptable.");
return -202;
}
break;
case 1:
for (indx = (RecvLen - 2); indx <= (RecvLen - 1); indx++)
{
tmpStr = tmpStr + string.Format("{0:X2}", RecvBuff[indx]);
}
if (tmpStr.Trim() != "90 00")
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
else
{
tmpStr = "ATR : ";
for (indx = 0; indx <= (RecvLen - 3); indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
break;
case 2:
for (indx = 0; indx <= (RecvLen - 1); indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
break;
}
}
catch (IndexOutOfRangeException)
{
return -200;
}
}
return retCode;
}
功能 authenticateBlock 如下
private bool authenticateBlock(String block)
{
ClearBuffers();
/*SendBuff[0] = 0xFF; // CLA
SendBuff[2] = 0x00; // P1: same for all source types
SendBuff[1] = 0x82; // INS: for stored key input
SendBuff[3] = 0x00; // P2 : Memory location; P2: for stored key input
SendBuff[4] = 0x05; // P3: for stored key input
SendBuff[5] = 0x01; // Byte 1: version number
SendBuff[6] = 0x00; // Byte 2
SendBuff[7] = (byte)int.Parse(block); // Byte 3: sectore no. for stored key input
SendBuff[8] = 0x60; // Byte 4 : Key A for stored key input
SendBuff[9] = (byte)int.Parse("1"); // Byte 5 : Session key for non-volatile memory
*/
SendBuff[0] = 0xD4;
SendBuff[1] = 0x4A;
SendBuff[2] = 0x01;
SendBuff[3] = 0x00;
SendBuff[4] = (byte) int.Parse(block);
SendBuff[5] = 0xFF;
SendBuff[6] = 0xFF;
SendBuff[7] = 0xFF;
SendBuff[8] = 0xFF;
SendBuff[9] = 0xFF;
SendBuff[10] = 0xFF;
/*SendLen = 0x0A;
RecvLen = 0x02;*/
SendLen = 4;
RecvLen = 255;
retCode = SendAPDUandDisplay(2);
if (retCode != Card.SCARD_S_SUCCESS)
{
//MessageBox.Show("FAIL Authentication!");
return false;
}
return true;
}
这里要注意的一件奇怪的事情是,无论我在sendBuff中设置什么值,这个函数总是返回真值,并且写入数据代码“第一个代码块”返回写入成功消息
但是,当我在我的情况下读取那个块“5”时执行写入数据代码之后,那里什么都没有。我的读取块代码返回一个空字符串,当我尝试仔细检查数据是否已写入并且我的错误代码无法读取时,我使用外部软件来验证是否添加了值,该软件也不会显示数据我写的并得到了写成功的消息。
好的,下面是我用来读取块 5 的代码。
public string readBlock(String Block)
{
string tmpStr = "";
int indx;
if (authenticateBlock(Block))
{
ClearBuffers();
/*
SendBuff[0] = 0xFF; // CLA
SendBuff[1] = 0xB0;// INS
SendBuff[2] = 0x00;// P1
SendBuff[3] = (byte)int.Parse(Block);// P2 : Block No.
SendBuff[4] = (byte)int.Parse("16");// Le
*/
SendBuff[0] = 0xD4;
SendBuff[1] = 0x40;
SendBuff[2] = 0x01;
SendBuff[3] = 0x30;
SendBuff[4] = byte.Parse(Block.ToString(), System.Globalization.NumberStyles.HexNumber);
SendBuff[5] = 0xFF;
SendBuff[6] = 0xFF;
SendBuff[7] = 0xFF;
SendBuff[8] = 0xFF;
SendBuff[9] = 0xFF;
SendBuff[10] = 0xFF;
//SendLen = 5;
//RecvLen = SendBuff[4] + 2;
SendLen = 5;
RecvLen = 255;
retCode = SendAPDUandDisplay(2);
if (retCode == -200)
{
return "outofrangeexception";
}
if (retCode == -202)
{
return "BytesNotAcceptable";
}
if (retCode != Card.SCARD_S_SUCCESS)
{
return "FailRead";
}
// Display data in text format
for (indx = 0; indx <= RecvLen - 1; indx++)
{
tmpStr = tmpStr + Convert.ToChar(RecvBuff[indx]);
}
return (tmpStr);
}
else
{
return "FailAuthentication";
}
}
请注意,在检查读取器是否已连接后调用 readblock 方法,如果是这样,那么我调用 readblock方法并返回一个空字符串
正如您在评论中看到的那样,我已经尝试了几个值,但似乎没有任何帮助,已经 3 天了,我仍然被困在这里。
有人可以帮我弄清楚我在哪里做错了,我应该发送什么值来验证块?
请帮我一个忙,如果有人知道我的代码中的问题或想要更正我在sendBuff[]中设置的值,请在 C# 代码中引用它们,以便我可以使用您希望我实现的解决方案
任何真诚的帮助都将受到高度重视,在此先感谢。