我有一个看似简单的任务,即从芯片卡读取未加密的数据与Java。我对智能卡毫无经验,我希望有人能给我指一下正确的方向。
我用javax创建了一个项目。smartcardio库,虽然它像我的信用卡一样有魅力(识别读卡器,识别购物车插入,建立卡连接),但它不适用于我试图读取的卡。
问题是该卡不符合智能卡标准(我相信),因为当我将该卡插入读卡器时,我得到了SCARD_E_NO_SMARTCARD
错误。
我没有关于数据如何实际存储在卡上的任何文档,但我想(如果可能的话)只是戳一下,弄清楚它。我也不需要写入卡片,只需要读取存储在卡片上的数据。
我想创建一个CardTerminal实现,允许我只是发送任意命令到卡,而不是启动一个协议。
这是我的:
import java.util.List;
import javax.smartcardio.*;
public class SReader {
public static int listCounted() {
TerminalFactory factory = TerminalFactory.getDefault();
try {
List terminals = factory.terminals().list();
CardTerminal ter = (CardTerminal)terminals.get(0);
ter.waitForCardPresent(3000000);
if(ter.isCardPresent())
{
System.out.println("Card present");
// this causes the issue
Card ca = ter.connect("*");
System.out.println(ca);
}
System.out.println( ((CardTerminal)terminals.get(0)).isCardPresent());
return terminals.size();
} catch (CardException e) {
e.printStackTrace();
}
return 0;
}
public static void main(String[] args) {
listCounted();
}
}
,这是我插入卡片时得到的错误信息:
Card present
javax.smartcardio.CardNotPresentException: No card present
at java.smartcardio/sun.security.smartcardio.TerminalImpl.connect(TerminalImpl.java:83)
at Smaca/com.Smaca.SReader.listCounted(SReader.java:35)
at Smaca/com.Smaca.SReader.main(SReader.java:58)
Caused by: sun.security.smartcardio.PCSCException: SCARD_E_NO_SMARTCARD
at java.smartcardio/sun.security.smartcardio.PCSC.SCardConnect(Native Method)
at java.smartcardio/sun.security.smartcardio.CardImpl.<init>(CardImpl.java:97)
at java.smartcardio/sun.security.smartcardio.TerminalImpl.connect(TerminalImpl.java:79)
... 2 more
我想我需要写一个自定义的TerminalFactory实现能够读取卡?我已经搜索了好几天,想找到一个关于如何做到这一点的例子,但没有找到任何有用的东西。我也不确定这种方法是否适合我想要实现的目标。
任何允许我这样做的跨平台解决方案(node.js, python, Java)都可以。
任何帮助都非常感谢!
谢谢,汤姆
您的卡是同步I2C存储卡(AT24C16)。与异步卡不同,你的读卡器必须显式地支持它。
查看您的阅读器文档并检查是否(以及哪些)支持I2C存储卡。
如果您的读卡器支持I2C卡,那么应该描述如何与此特定卡通信。可能的选项通常是:
-
使用特殊的APDU命令—这种方式可以直接在java中使用
javax.smartcardio
-
使用额外的阅读器API—您可能需要离开
javax.smartcardio
并使用一些供应商提供的库(几乎总是本机)并从java(例如使用JNA)调用它
如果您的读卡器不支持这张卡,您必须换另一个读卡器。对于java,首选带有APDU接口的阅读器(见上文)。
EDIT>
对于伪apdu,您需要使用"direct"
模式连接到阅读器(这意味着您想直接与阅读器通信):
Card ca = ter.connect("direct");
那么伪apdu应该可以工作。AT24C16的典型通信序列如下(参见《ACR39系列-参考手册》第8.2节)。):
SELECT_CARD_TYPE——
FF A4 00 00 01 02
(type 0x02 for 32、64、128、256、512和1024千比特I2C卡)SELECT_PAGE_SIZE—
FF 01 00 00 01
(0x04 for 16 byte page),READ_MEMORY_CARD/WRITE_MEMORY_CARD根据需要
祝你项目顺利!