如何使用javax.smartcardio检测desfire卡?

如何使用javax.smartcardio检测desfire卡?,java,smartcard,mifare,Java,Smartcard,Mifare,我拼凑了以下代码示例,使用javax.smartcardio库检测Mifare智能卡。此代码适用于列出的Mifare类型 公共类DetectCardTester{ 专用静态最终字符串协议=“T=1”; 静态映射已知\u卡\u类型=ImmutableMap.builder() .put(“00-01”、“Mifare 1K”) .put(“00-02”、“Mifare 4K”) .put(“00-03”,“Mifare超轻”) .put(“00-26”,“Mifare Mini”) .build(

我拼凑了以下代码示例,使用javax.smartcardio库检测Mifare智能卡。此代码适用于列出的Mifare类型

公共类DetectCardTester{
专用静态最终字符串协议=“T=1”;
静态映射已知\u卡\u类型=ImmutableMap.builder()
.put(“00-01”、“Mifare 1K”)
.put(“00-02”、“Mifare 4K”)
.put(“00-03”,“Mifare超轻”)
.put(“00-26”,“Mifare Mini”)
.build();
公共静态void main(字符串…参数){
试一试{
final TerminalFactory TerminalFactory=SmartcardTerminalFactory.create();
System.out.println(“将卡放在读卡器上”);
最终卡=等待卡(终端区,3秒);
最终ATR ATR=card.getATR();
最终字节[]字节=atr.getBytes();
System.out.println(“ATR=“+String.valueOf(Hex.encodeHex(bytes,false)));
if(bytes!=null&&bytes.length>13){
String typeCode=String.format(“%02X-%02X”,字节[13],字节[14]);
if(已知卡片类型。容器(类型代码)){
System.out.println(“已知类型:+Known_CARD_TYPES.get(typeCode));
}否则{
System.out.println(“未知类型:+typeCode”);
}
}
//TODO:检测火灾卡
}捕获(可丢弃的t){
t、 printStackTrace();
}
}
公共静态卡等待卡(最终终端工厂、最终整数数量、最终临时单位)抛出CardException{
LocalDateTime timeout=now().plus(数量,单位);
while(现在().isBefore(超时)){
可选cardTerminal=getCardPresentTerminal(terminalFactory);
if(cardTerminal.isPresent()){
返回cardTerminal.get().connect(协议);
}
}
抛出新卡NotPresentException(“等待卡超时”);
}
私有静态可选getCardPresentTerminal(最终终端TerminalFactory TerminalFactory)引发CardException{
列表端子=terminalFactory.terminals().List();
用于(卡端子卡端子:端子){
if(cardTerminal.isCardPresent()){
返回可选。of(cardTerminal);
}
}
用于(卡端子卡端子:端子){
//waitForCardPresent/缺席不适用于某些Jacax.smartcard.io实现
//即OSXhttp://bugs.java.com/view_bug.do?bug_id=7195480
//这就是为什么我们有上面的即时检查
如果(卡片终端。等待卡片当前(250)){
返回可选。of(cardTerminal);
}
}
返回可选的.empty();
}
}
我使用以下资源将此代码组合在一起:

我想实现TODO注释来检测Desfire卡。如果我将Desfire卡放在屏幕上,则读取此代码仅输出:

Place card on the reader
ATR=3B8180018080
我发现这个问题有点帮助,但我遗漏了一些东西。所讨论的卡的HistoricalByte是0x80,我找不到任何信息

如果可能的话,我将非常感谢对上述代码示例进行扩展,以便它能够检测到Desfire卡类型。

重置答案(ATR)可能是您拥有的卡的一个很好的指示。您所追求的规范称为“7816-3”第8节。这实际上是一个付费的规范,但如果你谷歌好

无论如何,SIM卡规格很难理解,它们定义得很好,但您需要深入到位级别才能完全理解它

ATR以字节为单位进行解码,让我们解码您的特定ATR:

字节1称为“TS”,它被定义为3B或3F,其中3F表示使用的“逆约定”,3B表示“直接约定”

字节2称为“T0”,它被定义为“格式字符”。字节“8”的第一个半字节表示Y1参数,第二个半字节表示“K”参数。 您的“T0”第一个字节Y1=8,第二个字节K=1 Y1参数8=(二进制)1000表示只跟随TA1参数。 如果它是9=(二进制)1001,表示TA1接通(1),TB1断开(0),TC1断开(0),TD1接通(1)。 K定义历史字节的数量,即在您的案例中为1个历史字节

长话短说,是的,“80”是您的历史字节(在7816-4规范中定义)。 80是您可以拥有的最基本的历史字节。 80是“类别/状态指示器”,所有80的定义是指:

A status indicator (one, two or three bytes) may be present in an optional COMPACT-TLV data object
关键词是“可能存在”,即在您的情况下,他们决定不包括任何进一步的信息


回到您的问题,检查与准确值“3B8180018080”匹配的ATR应足以识别DESfire卡。但是,在我的应用程序中,我还使用了特定文件的存在(即,仅在desfire卡上找到)、文件内容,或AIDS提供的特定于卡的应用程序,以更准确地对卡进行分类。

如何为您的卡定制ATS?还是发送GetVersion?或者用本地DESFire而不是wrapped发送一些命令。我没有其他选择,因为它是ISO14443-4A。即使使用SAK(Java中不可用),您也可能会发现冲突。谢谢您的建议。我不确定如何使用Java发送ATS,也不确定如何使用它来确保该卡是Desfire卡。我确实想过使用GetVersion,但感觉像是黑客!ATS将专门针对您的卡,而不是DESFire,至少我认为是这样。然后,它是您在卡上配置的东西。关于GetVersion作为一个黑客,我认为考虑到它是一个4A类型的卡,否则将是困难的。实际上,有人可以在JavaCard上实现一个类似的命令,并假装它是一张DESFire卡:(卢多维奇·卢梭写的)将atr映射到card上相当不错;Stil