如何检查 INITIALIZE UPDATE 和 EXTERNAL AUTHENTICATE 的正确性?
Posted
技术标签:
【中文标题】如何检查 INITIALIZE UPDATE 和 EXTERNAL AUTHENTICATE 的正确性?【英文标题】:How can I check INITIALIZE UPDATE and EXTERNAL AUTHENTICATE correctness? 【发布时间】:2014-06-07 04:46:23 【问题描述】:我通过 opensc-tool 向我的 java 卡发送了 80 50 00 00 08 00 00 00 00 00 00 00 00
[INITILIZE UPDATE 命令] 并收到了来自卡的响应 00 00 11 60 01 00 8A 79 0A F9 FF 02 00 11 79 11 36 5D 71 00 A5 A5 EC 63 BB DC 05 CC
[Init Response] .
如你所见:
在命令中,我发送00 00 00 00 00 00 00 00
作为主机挑战,并在响应中:
00 00 11 60 01 00 8A 79 0A F9
= 关键多元化数据
FF 02
= 关键信息
00 11 79 11 36 5D 71 00
= 卡片挑战
A5 A5 EC 63 BB DC 05 CC
= 卡密码
现在我想检查一下自己,卡密码是否正常。我该怎么做?例如,我在 3DES 加密算法下加密 this 站点中的 00 00 00 00 00 00 00 00
[使用我的卡的密钥 = 4041...4F
],但输出与我上面写的卡密码不相等。为什么?
接下来的问题是,如果我想向卡发送EXTERNAL AUTHENTICATION命令,它的数据字段是什么(在上面的INITILIZE UPDATE之后)?
更新:
这是 GPJ 输出:
C:\Users\ghasemi\Desktop\gpj-20120310>GPJ
C:\Users\ghasemi\Desktop\gpj-20120310>java -jar gpj.jar
Found terminals: [PC/SC terminal ACS CCID USB Reader 0]
Found card in terminal: ACS CCID USB Reader 0
ATR: 3B 68 00 00 00 73 C8 40 12 00 90 00
.
.
.
DEBUG: Command APDU: 00 A4 04 00 08 A0 00 00 00 03 00 00 00
DEBUG: Response APDU: 6F 10 84 08 A0 00 00 00 03 00 00 00 A5 04 9F 65 01 FF 90 00
Successfully selected Security Domain OP201a A0 00 00 00 03 00 00 00
DEBUG: Command APDU: 80 50 00 00 08 7F 41 A9 E7 19 37 83 FA
DEBUG: Response APDU: 00 00 11 60 01 00 8A 79 0A F9 FF 02 00 1B 9B 95 B9 5E 5E BC BA 51 34 84 D9 C1 B9 6E 90 00
DEBUG: Command APDU: 84 82 00 00 10 13 3B 4E C5 2C 9E D8 24 50 71 83 3A 78 AE 75 23
DEBUG: Response APDU: 90 00
DEBUG: Command APDU: 84 82 00 00 08 13 3B 4E C5 2C 9E D8 24
DEBUG: Response APDU: 90 00
C:\Users\ghasemi\Desktop\gpj-20120310>
所以:
Host_Challenge :: 7F41A9E7193783FA
Diversification_Data :: 0000116001008A790AF9
Key_Information :: FF02
Sequence_Counter :: 001B
Card_Challenge :: 9B95B95E5EBC
Card_Cryptogram :: BA513484D9C1B96E
Host_Cryptogram[16,24] = 13 3B 4E C5 2C 9E D8 24
现在,让我们手动制作 Host_Cryptogram:
Derivation_data=derivation_const_ENC|sequence_counter|0000 0000 0000 0000 0000 0000
Derivation_Data = 0182001B000000000000000000000000
k_ENC :: 404142434445464748494A4B4C4D4E4F
IV = 00 00 00 00 00 00 00 00
S_ENC = encrypt(TDES_CBC, K_ENC, IV, derivation_data)
所以:
我使用了http://tripledes.online-domain-tools.com/,它对上述值的输出是:
S_ENC = 448b0a5967ca246d058703ff0c694f15
还有:
Padding_DES = 80 00 00 00 00 00 00 00
Host_auth_data = sequence_counter | card_challenge | host_challenge | padding_DES
IV = Card_Cryptogram :: BA513484D9C1B96E
host_cryptogram = encrypt(TDES_CBC, S_ENC, IV, host_auth_data)
所以:
Host_Authentication_Data : 001B9B95B95E5EBC7F41A9E7193783FA8000000000000000
我再次使用http://tripledes.online-domain-tools.com/
和:
Host_Cryptogram : 3587b531db71ac52392493c08cff189ce7b9061029c63b62
所以:
Host_Cryptogram[16,24] = e7b9061029c63b62
为什么这两种方式[手动和GPJ输出]给我们两个主机密码?
【问题讨论】:
【参考方案1】:从您发送的 INITIALIZE UPDATE 命令中,您会得到
host_challenge = 00 00 00 00 00 00 00 00
响应 INITIALIZE UPDATE 命令,您会得到 p>
diversification_data = 00 00 11 60 01 00 8A 79 0A F9
key_information = FF 02
sequence_counter = 00 11
card_challenge = 79 11 36 5D 71 00
card_cryptogram = A5 A5 EC 63 BB DC 05 CC
关键信息表明SCP02(02
)。密钥多样化数据可用于导出特定于卡的 K_ENC。假设我们有一个像这样的 K_ENC
K_ENC = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
然后我们可以像这样导出会话加密密钥
derivation_const_ENC = 01 82
derivation_data = derivation_const_ENC | sequence_counter | 00 00 00 00 00 00 00 00 00 00 00 00
IV = 00 00 00 00 00 00 00 00
S_ENC = encrypt(TDES_CBC, K_ENC, IV, derivation_data)
接下来,我们可以组装用于计算主机密码的认证数据:
padding_DES = 80 00 00 00 00 00 00 00
host_auth_data = sequence_counter | card_challenge | host_challenge | padding_DES
那么我们可以使用会话加密密钥来加密认证数据:
IV = 00 00 00 00 00 00 00 00
host_cryptogram = encrypt(TDES_CBC, S_ENC, IV, host_auth_data)
加密身份验证数据的最后 8 个字节是我们将发送到卡的实际主机密码:
EXTERNAL_AUTHENTICATE_data = host_cryptogram[16, 24]
现在我们可以组装 EXTERNAL AUTHENTICATE 命令了:
EXTERNAL_AUTHENTICATE = 84 82 03 00 08 | EXTERNAL_AUTHENTICATE_data
然后我们可以计算 S_MAC 密钥(类似于获取上面的 S_ENC)和该命令的 MAC,并将其附加到命令数据中,以获得可以发送到卡的完整 EXTERNAL AUTHENTICATE 命令:
EXTERNAL_AUTHENTICATE = 84 82 03 00 10 | EXTERNAL_AUTHENTICATE_data | MAC
更新
使用http://tripledes.online-domain-tools.com/复现GPJ的结果
您的 K_ENC 是 404142434445464748494A4B4C4D4E4F
。在线工具不正确支持 2-key-3DES,因此您必须先将密钥转换为 3-key 形式:
K_ENC = 404142434445464748494A4B4C4D4E4F4041424344454647
使用此密钥和零 IV 来加密派生数据 (0182001B000000000000000000000000
)。你得到
S_ENC = fb063cc2e17b979b10e22f82110234b4
在三键符号中,这是
S_ENC = fb063cc2e17b979b10e22f82110234b4fb063cc2e17b979b
使用此密钥和零 IV 加密主机身份验证数据 (001b9b95b95e5ebc7f41a9e7193783fa8000000000000000
):
HOST_CRYPTOGRAM = 773e790c91acce3167d99f92c60e2afd133b4ec52c9ed824
【讨论】:
K_ENC 是卡的加密密钥。这是您或卡制造商设置的任何内容。例如,它可以是40 41 .. 4F
(或使用主密钥派生的特定于卡的密钥)。
应该是host_auth_data
。
在向 SO 发布问题之前,您是否尝试过用谷歌搜索这些问题?
M 消息A 验证C ode 确保完整性和真实性。在 SCP02 的情况下,这在 GP2.2 E.4.4 APDU 命令 C-MAC 生成和验证中进行了描述
@abraham 我对用于加密主机密码的 IV 错误。应使用零 IV。请参阅我关于如何计算密码的更新答案。以上是关于如何检查 INITIALIZE UPDATE 和 EXTERNAL AUTHENTICATE 的正确性?的主要内容,如果未能解决你的问题,请参考以下文章
我应该如何解决“未定义路由 [admin.conditions.update]”。错误?
如何修复方法'initialize()'定义了Objective-C类方法'initialize',这是Swift 4中不允许的?