Cryptography 如何检查初始化更新和外部身份验证的正确性?

Cryptography 如何检查初始化更新和外部身份验证的正确性?,cryptography,smartcard,javacard,apdu,globalplatform,Cryptography,Smartcard,Javacard,Apdu,Globalplatform,我通过opensc工具向我的java卡发送了80 50 00 00 08 00 00 00 00 00 00[初始化更新命令],并收到00 11 60 01 00 8A 79 0A F9 FF 02 00 11 79 11 11 36 5D 71 00 A5 EC 63 BB DC 05 CC[初始化响应] 如你所见: 在命令中,我以主机质询的形式发送00,并在响应中: 00 11 60 01 00 8A 79 0A F9=关键多元化数据 FF 02=关键信息 00 11 79 11 36 5D

我通过opensc工具向我的java卡发送了
80 50 00 00 08 00 00 00 00 00 00
[初始化更新命令],并收到
00 11 60 01 00 8A 79 0A F9 FF 02 00 11 79 11 11 36 5D 71 00 A5 EC 63 BB DC 05 CC
[初始化响应]

如你所见:

在命令中,我以主机质询的形式发送
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加密算法[使用我的卡的密钥=
4041…4F
]在站点中加密
00 00
,但输出不等于我上面写的卡密码。为什么?

下一个问题是,如果我想向卡发送外部身份验证命令,它的数据字段是什么(在上面的初始化更新之后)

更新:

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)
Host_Cryptogram : 3587b531db71ac52392493c08cff189ce7b9061029c63b62
Host_Cryptogram[16,24] = e7b9061029c63b62
这是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
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
现在,让我们手动创建主机密码:

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)
Host_Cryptogram : 3587b531db71ac52392493c08cff189ce7b9061029c63b62
Host_Cryptogram[16,24] = e7b9061029c63b62
所以:

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
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
我使用了,其对上述值的输出为:

S_ENC = 448b0a5967ca246d058703ff0c694f15
和:

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
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
所以:

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
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
再说一次,我用了

和:

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)
Host_Cryptogram : 3587b531db71ac52392493c08cff189ce7b9061029c63b62
Host_Cryptogram[16,24] = e7b9061029c63b62
所以:

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)
Host_Cryptogram : 3587b531db71ac52392493c08cff189ce7b9061029c63b62
Host_Cryptogram[16,24] = e7b9061029c63b62

为什么这两种方式[手动和GPJ输出]为我们提供了两种主机密码?

从您发送的初始化更新命令中,您可以得到

host_challenge = 00 00 00 00 00 00 00 00
作为对initializeupdate命令的响应,您将获得

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 = 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)
然后我们可以像这样导出会话加密密钥

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 = 84 82 03 00 10 | EXTERNAL_AUTHENTICATE_data | MAC
现在,我们可以组装外部身份验证命令:

EXTERNAL_AUTHENTICATE = 84 82 03 00 08 | EXTERNAL_AUTHENTICATE_data
然后,我们可以计算S_MAC密钥(类似于获取上述S_ENC)和该命令上的MAC,并将其附加到命令数据中,以获取可发送到卡的完整外部身份验证命令:

EXTERNAL_AUTHENTICATE_data = host_cryptogram[16, 24]
EXTERNAL_AUTHENTICATE = 84 82 03 00 10 | EXTERNAL_AUTHENTICATE_data | MAC

更新 用于重现GPJ的结果

您的K_ENC是
404142434445464748494A4B4C4D4E4F
。在线工具无法正确支持2键3D,因此必须先将该键转换为3键形式:

K_ENC = 404142434445464748494A4B4C4D4E4F4041424344454647
使用此密钥和零IV加密派生数据(
0182001B000000000000000000000000
)。你得到

在3键表示法中,这是

S_ENC = fb063cc2e17b979b10e22f82110234b4fb063cc2e17b979b
使用此密钥和零IV加密主机身份验证数据(
001B9B95B95E5EBC7F41A9E7193783FA80000000000000
):


K_ENC是卡的加密密钥。这是你或卡制造商设定的。例如,它可以是
40 41。。4F
(或使用主密钥派生的卡专用密钥)。这应该是
主机验证数据
。在向SO发布问题之前,您是否尝试搜索这些问题?消息验证代码确保完整性和真实性。对于SCP02,GP2.2 E.4.4 APDU命令C-MAC生成和Verification@abraham我对IV加密主机密码的看法是错误的。应使用零IV。请参阅我关于如何计算密码的更新答案。