如何计算 Retail-MAC(Single DES Plus Final Triple DES MAC) in SCP02 (Secure channel Protocol 02) with ICV encryption?
How to calculate Retail-MAC(Single DES Plus Final Triple DES MAC) in SCP02 (Secure channel Protocol 02) with ICV encryption?
我看到很多人在 C-MAC 代(零售 MAC)上寻求帮助。这个问题也包含答案。
这将有助于您获得足够的时间。
我用真卡测试过这个功能,效果很好。
注:
- 喜欢可以提高功能效率
- 如果您发现任何改进,请提出建议。
- 在您开始使用 Ext_Atuh 作为 CMAC 进行通信的 SCP 02 之前,请检查 SCP i 值。
- 此函数支持下一条命令的ICV加密。
public static byte[] generateCmac(byte []apdu,byte[]sMacSessionKey,byte[]icv) 抛出异常 {
if(sMacSessionKey.length == 16) {
byte []temp = sMacSessionKey.clone();
sMacSessionKey = new byte[24];
System.arraycopy(temp,0,sMacSessionKey,0,temp.length);
System.arraycopy(temp,0,sMacSessionKey,16,8);
}
byte []cMac = new byte[8];
byte []padding = {(byte)0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
int paddingRequired = 8 - (apdu.length) %8;
byte[] data = new byte[apdu.length + paddingRequired];
System.arraycopy(apdu, 0, data, 0, apdu.length);
System.arraycopy(padding, 0, data, apdu.length,paddingRequired);
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
Cipher singleDesCipher = Cipher.getInstance("DES/CBC/NoPadding",
"SunJCE");
SecretKeySpec desSingleKey = new SecretKeySpec(sMacSessionKey, 0, 8,
"DES");
SecretKey secretKey = new SecretKeySpec(sMacSessionKey, "DESede");
// Calculate the first n - 1 block. For this case, n = 1
IvParameterSpec ivSpec = new IvParameterSpec(icv);
singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
// byte ivForLastBlock[] = singleDesCipher.doFinal(data, 0, 8);
int blocks = data.length / 8;
for (int i = 0; i < blocks - 1; i++) {
singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
byte[] block = singleDesCipher.doFinal(data, i * 8, 8);
ivSpec = new IvParameterSpec(block);
}
int offset = (blocks - 1) * 8;
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
cMac = cipher.doFinal(data, offset, 8);
ivSpec = new IvParameterSpec(new byte[8]);
singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
icvNextCommand = singleDesCipher.doFinal(cMac);
System.out.println("icvNextCommand"+Utility.bytesToHex(icvNextCommand, icvNextCommand.length));
return cMac;
}
一种更简单的替代方法是使用Signature.ALG_DES_MAC8_ISO9797_1_M2_ALG3
(如果卡支持)来计算SCP02中C-MAC的retail MAC值。
注意:CMAC是消息认证码,SCP02中根本没有使用。
编辑> 对于 PC 端,请考虑 ISO9797Alg3Mac from Bouncy Castle。
我看到很多人在 C-MAC 代(零售 MAC)上寻求帮助。这个问题也包含答案。 这将有助于您获得足够的时间。 我用真卡测试过这个功能,效果很好。
注:
- 喜欢可以提高功能效率
- 如果您发现任何改进,请提出建议。
- 在您开始使用 Ext_Atuh 作为 CMAC 进行通信的 SCP 02 之前,请检查 SCP i 值。
- 此函数支持下一条命令的ICV加密。
public static byte[] generateCmac(byte []apdu,byte[]sMacSessionKey,byte[]icv) 抛出异常 {
if(sMacSessionKey.length == 16) {
byte []temp = sMacSessionKey.clone();
sMacSessionKey = new byte[24];
System.arraycopy(temp,0,sMacSessionKey,0,temp.length);
System.arraycopy(temp,0,sMacSessionKey,16,8);
}
byte []cMac = new byte[8];
byte []padding = {(byte)0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
int paddingRequired = 8 - (apdu.length) %8;
byte[] data = new byte[apdu.length + paddingRequired];
System.arraycopy(apdu, 0, data, 0, apdu.length);
System.arraycopy(padding, 0, data, apdu.length,paddingRequired);
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
Cipher singleDesCipher = Cipher.getInstance("DES/CBC/NoPadding",
"SunJCE");
SecretKeySpec desSingleKey = new SecretKeySpec(sMacSessionKey, 0, 8,
"DES");
SecretKey secretKey = new SecretKeySpec(sMacSessionKey, "DESede");
// Calculate the first n - 1 block. For this case, n = 1
IvParameterSpec ivSpec = new IvParameterSpec(icv);
singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
// byte ivForLastBlock[] = singleDesCipher.doFinal(data, 0, 8);
int blocks = data.length / 8;
for (int i = 0; i < blocks - 1; i++) {
singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
byte[] block = singleDesCipher.doFinal(data, i * 8, 8);
ivSpec = new IvParameterSpec(block);
}
int offset = (blocks - 1) * 8;
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
cMac = cipher.doFinal(data, offset, 8);
ivSpec = new IvParameterSpec(new byte[8]);
singleDesCipher.init(Cipher.ENCRYPT_MODE, desSingleKey, ivSpec);
icvNextCommand = singleDesCipher.doFinal(cMac);
System.out.println("icvNextCommand"+Utility.bytesToHex(icvNextCommand, icvNextCommand.length));
return cMac;
}
一种更简单的替代方法是使用Signature.ALG_DES_MAC8_ISO9797_1_M2_ALG3
(如果卡支持)来计算SCP02中C-MAC的retail MAC值。
注意:CMAC是消息认证码,SCP02中根本没有使用。
编辑> 对于 PC 端,请考虑 ISO9797Alg3Mac from Bouncy Castle。