问题读取智能卡
Posted
技术标签:
【中文标题】问题读取智能卡【英文标题】:Issue reading smart card 【发布时间】:2014-05-29 09:51:07 【问题描述】:我有一个阅读器,它的文档几乎与这个完全相同:http://www.jinmuyu.com/download/JMY680A_EN.pdf 主要区别在于,我的读者声称它还支持 B 型卡。
我有三张 ISO 14443 卡,我连续测试,代码如下:
byte[] rs = null;
Thread.Sleep(500);
// Set module Idle
Random r = new Random();
byte rInt = (byte) r.Next(0, 255);
rs = send(new byte[] 0x12, rInt );
if (rs[1] == 0xED)
throw new Exception("Failed set idle");
Thread.Sleep(500);
//// Request B
//rs = send(new byte[] 0x60, 0x00, 0x00 );
//if (rs[1] == 0x9F)
// throw new Exception("Failed card requestB");
// RequestA
rs = send(new byte[] 0x20, 0x00 );
if (rs[1] == 0xDF)
throw new Exception("Failed card requestA");
// Reset cardA
rs = send(new byte[] 0x30 );
if(rs[1] == 0xCF)
throw new Exception("Failed card reset");
// Do other work, Send some APDU to card, etc.
// ........
// Exit program
大多数情况下,此代码适用于所有三张卡。
但是,有时,当我将其中一张卡靠近读卡器时,卡请求 A(RequestA
呼叫)
通话失败。然后这张卡总是会失败,直到我给读卡器带来一张新卡。
有谁知道是什么原因造成的?也许我在通话之间需要一些延迟?或者在调用RequestA
之前需要调用其他一些(ISO14443相关)函数?
send
是使用SerialPort
类实现的方法。方式如下:
-
在每次调用 send 时,都会创建新的
SerialPort
对象
在上面创建的对象上调用Open
Write
和 Read
一些数据
在此方法实例中创建的对象上使用Close
关闭连接
顺便说一句。这是其中一张卡(读卡器失败一次)对 RequestA 命令的成功响应:
ID | ATQ | SAK
0xe1 0x8f 0x68 0xe6 0x04 0x00 0x28
【问题讨论】:
“失败”是什么意思?卡回答错误,或者您根本没有回答,或者您有来自串行的通信错误? @LorenzoDematté:我的意思是失败时抛出异常。根据文档,如果卡返回0xDF
作为第二个字节,则表示失败。
我明白了。这可能是很多事情。 0x20 命令似乎特定于您的读卡器,它可能和 ISO / Mifare 命令选择(激活)卡。 Iso 和 desfire 命令有一些不同的错误代码,具体取决于错误,但是......似乎只有你一个人知道读者告诉(或不告诉)你的内容
这是“廉价”阅读器的一个问题:他们实现自己的协议,然后你必须处理你得到的东西。该错误可能是卡错误,通信错误,等等。等等:我看到了你的编辑。这是您从其中一张卡片中得到的“正确”响应吗?
哦,好的。 Mifare 经典是......奇怪的东西。几乎是 A 型,但有自己的一套命令。但通常相当可靠。但我离题了(它们是我所知道的唯一具有 4 字节 UID 的卡)。当你失败后再次尝试时会发生什么?读卡器是否在连续轮询(它会再次尝试选择卡吗?)。您必须考虑到 PICC 中的传输可能非常不可靠,因此在失败前尝试 2/3 次是很正常的。
【参考方案1】:
我无法确定您的代码存在什么问题,但是当连接出错且未打开新连接时,这似乎是一个问题。因为 SerialPort 是您需要处理处置的硬件资源,所以 SerialPort 可能实现 IDisposable,这意味着您可以使用确保连接已关闭和处置。带一张新卡可能会这样做,但是当您使用同一张卡时,您仍然使用处于故障状态的串行端口。
【讨论】:
请在下面查看我对 jhonnash 的评论。通过第二次将卡带到读卡器 - 这发生在我重新启动程序并从头开始运行上面的代码之后 - 你认为在这种情况下 Dispose 仍然是一个问题吗? 是的,它可以,串行端口可能有一些未正确重置的状态。看到它实现了 IDisposable,如果是这样,请使用using
块。
我对 C# 有点陌生。我发现了这个:msdn.microsoft.com/en-us/library/3cc9y48w.aspx 你建议我在SerialPort.Close()
方法之后调用它?
还要注意如果我在代码中抛出 Failed card requestA 异常 - 到那时端口应该在之前的send
调用中关闭,但我会检查你的建议【参考方案2】:
当您将 cardA 放在读卡器附近时,它会失败。之后,每次将 cardA 靠近读卡器时,它都会失败。
我不确定,但我猜当它失败时,字节数组rs[1]
的第二个位置包含失败代码。因此,此后每次将 cardA 靠近读卡器时,它都会失败,因为字节数组的第 2 位置可能具有先前的值。
所以,请尝试清除字节数组,这可能会解决您的问题。
【讨论】:
第二次将同一张卡带到读卡器,我的意思是当我退出程序并再次运行它时 - 那么 rs 不能有旧值,对吗? (因为你可以看到没有循环 - 所以我只能在重新启动程序时将卡带到读卡器) 它会在之后的 3 到 4 次试验中接受它,还是一旦失败它就永远不会用同一张卡成功的场景......!!! 同一张卡总是一旦被阻塞一次就出问题了,如果我换卡就可以了... 我已经回答了这个问题:) ps。当我 更换 卡时,它会起作用,而且如果我现在使用旧卡 - 它被阻塞,它也会起作用...... 简报文件后;你有没有按照ISO1443
去按照5.2.26 ISO14443-4 TYPE-A card reset(RATS)
中定义的RATS Process
去呢以上是关于问题读取智能卡的主要内容,如果未能解决你的问题,请参考以下文章