Java “怎么做?”;Visa2“;关键多样化在Gemalto卡和GPP工具中起作用?
我有一堆Gemalto java卡,正如您在下面看到的,我同意使用以下方式进行相互身份验证: 因此,我尝试为上述通信重复主机密码生成。我有: 主钥匙=Java “怎么做?”;Visa2“;关键多样化在Gemalto卡和GPP工具中起作用?,java,cryptography,smartcard,emv,visa,Java,Cryptography,Smartcard,Emv,Visa,我有一堆Gemalto java卡,正如您在下面看到的,我同意使用以下方式进行相互身份验证: 因此,我尝试为上述通信重复主机密码生成。我有: 主钥匙=47454D58505245534F53414D504C45 基于: 主机挑战=2CA286A611F6CAFD 初始更新响应:4D00041849D08192420C3 FF01 31D644E9913234DD E1F0A6A462C71805 关键多元化数据=4D004184D08192420C3 密钥信息=FF01:因此使用了SCP01
47454D58505245534F53414D504C45
基于:
主机挑战=2CA286A611F6CAFD
初始更新响应:4D00041849D08192420C3 FF01 31D644E9913234DD E1F0A6A462C71805
- 关键多元化数据=
4D004184D08192420C3
- 密钥信息=
:因此使用了SCP01FF01
- 卡片质询=
31D644E9913234DD
- 卡密码=
E1F0A6A462C71805
- 数据=
4D00 9D081924 F001 4D00 9D081924 0F01
Static_ENC = Encrypt(MasterKey, Diversification_Data )
因此,使用,我有:
这意味着:
静态加密键=84f2a84ecdade8cacc9e7e07faebe4e6
为了计算ENC会话密钥,我再次使用了GlobalPlatform规范:
因此,我:
- 派生数据=
913234DD 2CA286A6 31D644E9 11F6CAFD
ENC_Session_键
是:
ENC\u Session\u Key=b1ed5ea3f69978274d2ffe0de467ec1c
最后,主机密码的生成和验证是通过将8字节卡质询和8字节主机质询串联在一起,形成一个16字节的块,并将该16字节数组与80 00
串联在一起来执行的。然后在CBC模式下使用ENC会话密钥以零ICV对此进行签名:
数据加密=31D644E9913234DD 2CA286A611F6CAFD 80000000000000
我有:
好吧,我试了两次以上步骤,每次都遇到错误的主机密码值!但是当我重复这些步骤并在我的问题中逐行写下这些步骤时,我终于注意到我的最终结果与我第一个问题的GPP结果相等!因此,我不想删除我的问题,而是把它保留在这里,供未来的观众观看 综上所述: 在智能卡中加入密钥多样化方案,在GlobalPlatform卡规范中提到的用于计算卡密码和MAC值的步骤上增加了一个步骤。这一步就是计算静态键 用于静态键计算的U数据为(): 初始更新响应数据的前两个字节是相同的
xxh xxh
,其字节[4:8]是IC序列号
使用主密钥在ECB模式下使用三重DES算法加密多样化数据,返回静态密钥。要检查卡密码,必须将主机质询的8字节与卡质询的8字节和“80000000000000”连接起来。 生成字符串后,然后在CBC模式下使用ENC会话密钥以零ICV对此进行签名
public static GPKeySet diversify(GPKeySet keys, byte[] diversification_data, Diversification mode, int scp) throws GPException {
try {
GPKeySet result = new GPKeySet();
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
for (KeyType v : KeyType.values()) {
if (v == KeyType.RMAC)
continue;
byte [] kv = null;
// shift around and fill initialize update data as required.
if (mode == Diversification.VISA2) {
kv = fillVisa(diversification_data, v);
} else if (mode == Diversification.EMV) {
kv = fillEmv(diversification_data, v);
}
// Encrypt with current master key
cipher.init(Cipher.ENCRYPT_MODE, keys.getKey(v).getKey(Type.DES3));
byte [] keybytes = cipher.doFinal(kv);
// Replace the key, possibly changing type. G&D SCE 6.0 uses EMV 3DES and resulting keys
// must be interpreted as AES-128
GPKey nk = new GPKey(keybytes, scp == 3 ? Type.AES : Type.DES3);
result.setKey(v, nk);
}
return result;
} catch (BadPaddingException |InvalidKeyException | IllegalBlockSizeException e) {
throw new GPException("Diversification failed.", e);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("Diversification failed.", e);
}
}
public static byte[] fillVisa(byte[] init_update_response, KeyType key) {
byte[] data = new byte[16];
System.arraycopy(init_update_response, 0, data, 0, 2);
System.arraycopy(init_update_response, 4, data, 2, 4);
data[6] = (byte) 0xF0;
data[7] = key.getValue();
System.arraycopy(init_update_response, 0, data, 8, 2);
System.arraycopy(init_update_response, 4, data, 10, 4);
data[14] = (byte) 0x0F;
data[15] = key.getValue();
return data;
}
Static_ENC = Encrypt(MasterKey, Diversification_Data )