在两种不同的场景中给出 6985 和 61xx 的初始化更新
Posted
技术标签:
【中文标题】在两种不同的场景中给出 6985 和 61xx 的初始化更新【英文标题】:Init update given 6985 and 61xx in two different scenario 【发布时间】:2015-04-27 05:00:45 【问题描述】:我有一个 java 卡,我写了一个小代码来发送 APDU 到 java 卡。在这里,当我发送 Init_Update 命令时,我得到 0x6985,例如:-
CMD -> 80 50 00 00 08 11 22 33 44 55 66 77 88
RES <- 6985
但是当我使用其他工具发送此命令时,它会给出所需的结果,例如:-
Transmit: 80 50 00 00 08 []
11 22 33 44 55 66 77 88 ."3DUfw.
Card answered: 61 1C
我的 java 代码适用于我拥有的其他 java 卡。谁能告诉我这种不同行为的原因是什么..
// full java code
public static void main(String[] args)
// TODO code application logic here
try
factory = TerminalFactory.getDefault();
terminals = factory.terminals().list();
terminal = terminals.get(0);
card = terminal.connect("*");
channel =card.getBasicChannel();
CommandAPDU cmdAPDU;
ResponseAPDU response;
byte[] select_isd = (byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 ;
cmdAPDU = new CommandAPDU(select_isd);
response = channel.transmit(cmdAPDU);
byte[] INIT_UPDATE = (byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,
(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 ;
cmdAPDU = new CommandAPDU(INIT_UPDATE);
response = channel.transmit(cmdAPDU);
catch( Exception ex)
其他工具日志如下:-
Card opened
12 bytes ATR received:
3B 68 00 00 00 73 C8 40 00 00 90 00
Transmit: 00 A4 04 00 08 [SELECT FILE]
A0 00 00 00 03 00 00 00 ........
Card answered: 61 12
Transmit: 00 C0 00 00 12 [GET RESPONSE]
Card answered: 90 00
6F 10 84 08 A0 00 00 00 03 00 00 00 A5 04 9F 65 o..............e
01 FF ..
Transmit: 80 50 00 00 08 []
11 22 33 44 55 66 77 88 ."3DUfw.
Card answered: 61 1C
但是当我运行我的 java 代码时,我得到 6985 的 INIT_UPDATE 命令。
如果我需要任何其他信息,请告诉我..
==新增=== 我试图在 JCOP shell 中运行我的脚本,我的脚本是这样的:-
/mode trace=on
/terminal
/atr
/send 80CAA08D05
/send 802E000014B555C94B0B2368B4840201808502032288020060
/send 80D8000000
/atr
/send 80500000081122334455667788
它给了我所需的结果。同样,我尝试在 java 中实现,我的新 java 代码如下所示:- =====新更新的JAVA代码===
factory = TerminalFactory.getDefault();
terminals = factory.terminals().list();
terminal = terminals.get(0);
card = terminal.connect("*");
channel =card.getBasicChannel();
CommandAPDU cmdAPDU;
ResponseAPDU response;
byte[] x = (byte) 0x80, (byte) 0xCA, (byte) 0xA0,(byte) 0x8D,(byte)0x05;
byte[] y = remove command for security reasons;
byte[] z = (byte) 0x80, (byte) 0xD8, (byte) 0x00, (byte) 0x00, (byte) 0x00; // it set default key
cmdAPDU = new CommandAPDU(x);
response = channel.transmit(cmdAPDU);
System.out.println(response.toString());
cmdAPDU = new CommandAPDU(y);
response = channel.transmit(cmdAPDU);
System.out.println(response.toString());
cmdAPDU = new CommandAPDU(z);
response = channel.transmit(cmdAPDU);
System.out.println(response.toString());
card.disconnect(true);
card = terminal.connect("*");
channel =card.getBasicChannel();
byte[] INIT_UPDATE = (byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 ;
cmdAPDU = new CommandAPDU(INIT_UPDATE);
response = channel.transmit(cmdAPDU);
【问题讨论】:
您是否在发送初始化更新之前选择了 ISD?或者在发送初始化更新之前发送 ATR。 如果可能,请添加这部分代码。 611C 表示有 0x1C = 28 个字节要读取。您应该使用 GET RESPONSE 命令 (00 C0 00 00 XX) 响应 61XX 以获取您的响应数据。 @anurag 我试图在初始化更新之前调用 ISD,它在其他工具中很好,但在 java 代码中 ISD 响应为 0x6112 但单元更新仍然给出 0x6985。什么是发送 atr? @abraham 我的卡是双界面卡,但我的读卡器只能接触,我正在用接触场景测试我的 java 代码.... 【参考方案1】:6985
表示不满足使用条件。由于您到目前为止没有使用任何密钥,这可能意味着该卡已被锁定或终止。
611C
是用于 APDU 通过 T=0 发送的状态字。 T=0 不会在同一个 APDU 中同时处理命令和响应(也称为“ISO 案例 4”),因此 ISO 案例 4 命令需要 GET RESPONSE
。要么第一个应用程序在看不见的地方处理这个问题(就像 Java Card 本身所做的那样)——结合两个 APDU——或者它创建一个 T=1 连接而不是 T=0 连接。
它与6985
状态字几乎没有关系,因为您希望在处理 INITIALIZE UPDATE 命令的业务逻辑之前生成此警告 - 只有在可以生成输出时才会处理该命令。
【讨论】:
其实我的卡并没有被锁定,因为它在其他工具中给出了611C,你是对的,javax.smartcard.io内部处理get response,所以我们不需要担心。我很担心为什么我的 java 代码用这张卡返回 6985。 @Maarten Bodewes:很抱歉不同意:69 85 表示不满足使用条件,而 security.conditions 不满足 由 69 82 表示。 @guidit 谢谢,经过大量编辑的答案。它有很多问题,但答案的要点保持不变。 @Maarten:很抱歉不同意:如果卡被终止或锁定,初始化更新命令永远不会给出 6985。而不是根据第 6.5.5 节下的 v2.2.1 上的规范映射指南 GP v2.1.1:如果卡被终止,则返回“6D00”响应。并且根据 GP2.2.1 规范:初始化更新命令适用于卡生命周期状态 (CLCS) 锁定,因为如果您通过安全会话 (SCP02) 将 CLCS 从安全移动到锁定,然后将 CLCS 移动回安全状态(从锁定状态)您需要通过 InitUpdate 和 External Authenticate 命令建立安全会话。【参考方案2】:-
对于 SW '6985'
根据规范现有 GP v2.1.1 在 v2.2.1 上实现的映射指南:在第 6.5.2 节下
" 如果安全通道当前在一个逻辑通道上处于活动状态,而不是发出此命令(初始化更新命令)的逻辑通道,则返回响应 '6985'。"
如果 Initialize Update 命令失败并显示 6985,请与此行为进行交叉检查。
-
对于 SW '611C'
如果信息对于单个响应数据字段来说太长,则卡应返回信息的开头,然后将 SW1-SW2 设置为“61XX”。然后后续的 GET RESPONSE 提供“XX”字节的信息。该过程可能会重复,直到卡发送 SW1-SW2 设置为“9000”。
在这种情况下,您需要发送 GET RESPONSE 命令,P3 为 1C,CARD 将返回 1C 字节的数据。
【讨论】:
我们如何处理安全通道之类的事情,我们只发送 80 50 00 00 08 11 22 33 44 55 66 77 88???? @Rohit : 80 50 00 00 08 11 22 33 44 55 66 77 88 只不过是初始化更新命令,它在外部验证命令的帮助下用于启动安全会话(SCP02 会话)。由于某些原因,初始化更新命令可能会给出 6985,其中一个我在上面解释过,即如果支持逻辑通道并且安全会话在一个逻辑通道中的安全域上处于活动状态,那么如果您尝试启动安全会话(通过发送 Initialized更新命令)在其他逻辑通道中的同一安全域上,然后初始化更新命令将给出 6985。 检查安全会话当前是否在其他逻辑通道中的同一安全域(您正在发送初始化更新命令)上处于活动状态。最好通过 Mange 通道命令(请参阅全局平台规范)关闭所有其他逻辑通道(如果可能),然后检查您的方案。 初始化更新命令可以给出 6985 的其他一些原因是: 1- 如果安全域上不存在 SCP02 密钥集(在其上发出初始化更新命令)。 SCP02 键组从 20 到 2F。请检查是否存在密钥集。 2- 如果安全域(在其中发出初始化更新命令)没有 SCP 能力(请参阅 UICC 配置规范,并参见 SD 安装参数中的标记 '81'),也请交叉检查 SCP 能力。跨度> 我发现 cod 很简单,获取基本频道并在同一频道上传输 INIT_update。很抱歉,您还想让我做什么还不清楚。为了您的信息,我用 Jcop shell 脚本尝试了这个,我的脚本就像 /mode trace=on /terminal /atr /send 80CAA08D05 /send 802E000014xxxxxxxxxx... /send 80D8000000 /atr #INITUPDATE /send 80500000081122334455667788 它工作正常并给出61xx【参考方案3】:您可以使用 BusHound 捕捉一些 APDU,然后在发送命令过程中比较和分析这两个工具之间的差异。
【讨论】:
我试过但没有找到发送命令的地方,例如:- 80 50 00 00 08 11 22 33 44 55 66 77 88【参考方案4】:我可以请你也试试这个程序吗?
public static void main(String[] args)
try
factory = TerminalFactory.getDefault();
terminals = factory.terminals().list();
terminal = terminals.get(0);
card = terminal.connect("*");
channel =card.getBasicChannel();
CommandAPDU cmdAPDU1;
CommandAPDU cmdAPDU2;
ResponseAPDU response1;
ResponseAPDU response2;
byte[] select_isd = (byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 ;
byte[] INIT_UPDATE = (byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 ;
cmdAPDU1 = new CommandAPDU(select_isd);
cmdAPDU2 = new CommandAPDU(INIT_UPDATE);
response1 = channel.transmit(cmdAPDU1);
response2 = channel.transmit(cmdAPDU2);
catch( Exception ex)
恐怕如果transmit
之间的new CommandAPDU
方法,重置卡和读卡器之间的连接。
更新:
如果上面的程序返回同样的错误,请也试试这个:
public static void main(String[] args)
try
factory = TerminalFactory.getDefault();
terminals = factory.terminals().list();
terminal = terminals.get(0);
card = terminal.connect("*");
channel =card.getBasicChannel();
CommandAPDU cmdAPDU;
ResponseAPDU response;
byte[] select_isd = (byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 ;
byte[] get_response=(byte)0x00,(byte)0xC0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x12;
byte[] INIT_UPDATE = (byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 ;
cmdAPDU = new CommandAPDU(select_isd);
response = channel.transmit(cmdAPDU);
cmdAPDU = new CommandAPDU(get_response);
response = channel.transmit(cmdAPDU);
cmdAPDU = new CommandAPDU(INIT_UPDATE);
response = channel.transmit(cmdAPDU);
catch( Exception ex)
热切期待您的回复。
更新 2:
我认为尝试 Python 脚本有助于找出问题所在。你也可以试试这个:
>>> from smartcard.System import readers
>>> from smartcard.util import toHexString
>>>
>>> r=readers()
#if you have more than one reader or a dual interface reader, put the right index in the below line instead of `0`
>>> connection = r[0].createConnection()
>>> connection.connect()
>>>
>>> SELECT = [0xA0, 0xA4, 0x04, 0x00, 0x08 , 0xA0 , 0x00 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 ]
>>> GET_RESPONSE = [ 0x00, 0xC0, 0x00, 0x00, 0x12]
>>> INIT_UPDATE= [0x80, 0x50, 0x00, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]
>>>
>>> data, sw1, sw2 = connection.transmit( SELECT)
>>> print "%s %x %x" % (data, sw1, sw2)
>>>
#if the sw1 and sw2 of above command is not `0x6112`, don't send GET_RESPOSE command.
>>> data, sw1, sw2 = connection.transmit( GET_RESPONSE)
>>> print "%s %x %x" % (data, sw1, sw2)
>>>
>>> data, sw1, sw2 = connection.transmit( INIT_UPDATE)
>>> print "%s %x %x" % (data, sw1, sw2)
请注意,上述脚本适用于 Python 2.7,您还必须安装 PySCard
【讨论】:
感谢您的建议。但是您的第一个示例返回 ResponseAPDU: 20 bytes, SW=9000 ResponseAPDU: 2 bytes, SW=6985 和第二个示例返回 ResponseAPDU: 20 bytes, SW=9000 ResponseAPDU: 2 bytes, SW=6f00 ResponseAPDU: 2 bytes, SW=6985 这是完全奇怪的行为。我不知道为什么会这样。 @rohitamitpathak 我可以请你试试我在 Updae-2 部分中添加到我的 asnwer 中的 Python 脚本吗? 我用 Jcop shell 脚本试过这个,我的脚本就像 /mode trace=on /terminal /atr /send 80CAA08D05 /send 802E000014xxxxxxxxxx... /send 80D8000000 /atr #INITUPDATE /send 80500000081122334455667788 它是工作正常并提供 61xx【参考方案5】:问题是 EXTERNAL UPDATE 命令必须紧跟在 INITIAL UPDATE 之后。如果您收到 61nn 响应并发送 C0 命令以从 INITIAL UPDATE 检索剩余数据,则 EXTERNAL AUTH 命令失败,指示“ 访问条件不满足" [6982];那么,您至少有两种可能的选择来解决这个问题:
-
以 T=1 协议模式连接您的阅读器
lResult=SCardConnect( *pphContext,
tszReaderName,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T1,//<--FORCE TO SCARD_PROTOCOL_T1,
pphCard,
&dwActiveProtocol) )); //<--VERIFY THAT THIS VALUE IS SETTED TO 2
调整您的引擎 APDU 发送器以使用 T1 协议来接收有关响应的信息,避免使用 getResp 命令
00 C0 00 00 nn
-
(我以为没关系,我还在做这个)
如果要使用 T0 协议,则必须重新发送两次 INITIAL UPDATE 命令,第一次是为了使用 C0 命令从响应中获取数据。第二次尝试将使用 C0 Apdu 命令重新建立丢失的安全通道。在这里,您可能需要某种机制来管理通道命令以关闭其他通道(请参阅https://globalplatform.org/wp-content/uploads/2018/06/GPC_Specification-2.2.1.pdf 第 11.7 段),因为您可能会收到 6985 作为响应,并且您的智能卡似乎无法正常执行初始更新。
【讨论】:
以上是关于在两种不同的场景中给出 6985 和 61xx 的初始化更新的主要内容,如果未能解决你的问题,请参考以下文章
Salesforce - 我可以在两种不同的对象类型上有一个查找字段吗?
大众运输+ RabbitMQ。在两种不同的消息类型之间共享一个队列
Pandas Dataframe:在两种完全不同的格式之间转换日期格式[重复]