gpt4 book ai didi

cryptography - 密码版本 5 的方法 key 推导 (MKD)

转载 作者:行者123 更新时间:2023-12-04 04:53:01 28 4
gpt4 key购买 nike

我正在开发用于 EMV 交易的软件,但我面临着雇佣我的公司的文档严重缺乏的问题。
其中之一是关于用于生成 ARQC 的 MKD(在第一个 GENERATE AC 期间)。我从消息请求中知道IAD如下:

0FA501A030F8000000000000000000000F000000000000000000000000000000



根据它的密码版本是 5,但我不知道 MKD。

有没有参与过这个主题的人知道我应该用来生成 ARQC 的 MKD 吗?

我很感激任何评论。
谢谢。

最佳答案

(在 Vanilla EMV 和通用核心规范的背景下)

引用 EMV 4.3 ,第 2 册,第 8.1.2 节:

The method for Application Cryptogram generation takes as input a unique ICC Application Cryptogram Master Key MKAC and the data selected as described in section 8.1.1, and computes the 8-byte Application Cryptogram in the following two steps:

  1. Use the session key derivation function specified in Annex A1.3 to derive an Application Cryptogram Session Key SKAC from the ICC Application Cryptogram Master Key MKAC and the 2-byte Application Transaction Counter (ATC) of the ICC.
  2. Generate the 8-byte Application Cryptogram by applying the MAC algorithm specified in Annex A1.2 to the data selected and using the Application Cryptogram Session Key derived in the previous step. For AES the 8-byte Application Cryptogram is created by setting the parameter s to 8.


MKAC 本身源自“颁发者(应用程序密码)主 key ”(第 8.3 节):

For a cryptogram defined by the Common Core Definitions with a Cryptogram Version of '5', the ICC Master Key shall be derived using the Option B method described in Annex A1.4.2.



有关详细说明,请参阅 EMV Book 2 中提到的附件。

我可以提供以下 java 代码(半测试但没有任何保证):
public static byte[] deriveMasterKey(byte[] issuerMasterKey, byte[] pan, byte[] panSequenceNumber) {
String concat;
if(((pan[pan.length-1]&0x0F)==0x0F)) {
String help=ByteArrayUtils.toString(pan);
concat = "0" + help.substring(0, help.length()-1) + ByteArrayUtils.toString(panSequenceNumber);
} else {
concat = ByteArrayUtils.toString(pan) + ByteArrayUtils.toString(panSequenceNumber);
}
logger.debug("Concat: " + concat);
byte[] concatBytes=ByteArrayUtils.fromSafeString(concat);
byte[] sha1Bytes = SwCryptUtils.sha1(concatBytes);
String sha1=ByteArrayUtils.toString(sha1Bytes);
logger.debug("X: " + sha1);
StringBuilder b1 = new StringBuilder();
StringBuilder b2 = new StringBuilder();
for(char c : sha1.toCharArray()) {
if(Character.isDigit(c)) {
b1.append(c);
} else {
b2.append((char)(c-('A'-'0')));
}
}
String y = b1.toString() + b2.toString();
logger.debug("Y': " + y);
y = y.substring(0, 16);
logger.debug("Y: " + y);
byte[] yBytes = ByteArrayUtils.fromSafeString(y);
byte[] leftBytes = SwCryptUtils.desEncryptEcb(issuerMasterKey, yBytes);
String left = ByteArrayUtils.toString(leftBytes);
logger.debug("Z_{L}': " + left);
byte[] yXorBytes = yBytes.clone();
for (int i = 0; i < yXorBytes.length; i++) {
yXorBytes[i]^=0xFF;
}
logger.debug("Y_{xor}': " + ByteArrayUtils.toString(yXorBytes));
byte[] rightBytes = SwCryptUtils.desEncryptEcb(issuerMasterKey, yXorBytes);
String right = ByteArrayUtils.toString(rightBytes);
logger.debug("Z_{R}': " + right);
String result=left+right;
logger.debug("MK:" + result);
return ByteArrayUtils.fromSafeString(result);
}

public static byte[] deriveCommonSessionKey(byte[] masterKey, byte[] atc) {
byte[] rBytes=Arrays.copyOf(atc, 8);
logger.debug("R: " + ByteArrayUtils.toString(rBytes));
byte[] f1Bytes=rBytes.clone();
f1Bytes[2]=(byte)0xF0;
logger.debug("F1: " + ByteArrayUtils.toString(f1Bytes));
byte[] f2Bytes=rBytes.clone();
f2Bytes[2]=(byte)0x0F;
logger.debug("F2: " + ByteArrayUtils.toString(f2Bytes));
byte[] f1EncBytes = SwCryptUtils.desEncryptEcb(masterKey, f1Bytes);
logger.debug("ENC(F1): " + ByteArrayUtils.toString(f1EncBytes));
byte[] f2EncBytes = SwCryptUtils.desEncryptEcb(masterKey, f2Bytes);
logger.debug("ENC(F2): " + ByteArrayUtils.toString(f2EncBytes));
byte[] result = ArrayUtils.addAll(f1EncBytes, f2EncBytes);
logger.debug("SK: " + ByteArrayUtils.toString(result));
return result;
}

public static byte[] generateApplicationCryptogram(byte[] sessionKey, byte[] terminalData, byte[] iccData) {
byte[] dataBytes = ArrayUtils.addAll(terminalData, iccData);
logger.debug("DATA: " + ByteArrayUtils.toString(dataBytes));
byte[] paddedDataBytes = ArrayUtils.add(dataBytes, (byte)0x80);
paddedDataBytes=Arrays.copyOf(paddedDataBytes, ((paddedDataBytes.length+7)/8)*8);
logger.debug("PADDED DATA: " + ByteArrayUtils.toString(paddedDataBytes));

byte[] skBytes=sessionKey;
byte[] skL = Arrays.copyOf(skBytes, 8);
logger.debug("SK_{L}: " + ByteArrayUtils.toString(skL));
byte[] skR = Arrays.copyOfRange(skBytes, 8, 16);
logger.debug("SK_{R}: " + ByteArrayUtils.toString(skR));

byte[] pom = SwCryptUtils.desEncryptCbcZeroIv(skL, paddedDataBytes);
logger.debug("POM: " + ByteArrayUtils.toString(pom));
pom=Arrays.copyOfRange(pom, pom.length-8, pom.length);
logger.debug("POM: " + ByteArrayUtils.toString(pom));
pom=SwCryptUtils.desDecryptEcb(skR, pom);
logger.debug("POM: " + ByteArrayUtils.toString(pom));
pom=SwCryptUtils.desEncryptEcb(skL, pom);
logger.debug("POM: " + ByteArrayUtils.toString(pom));
logger.debug("AC: " + ByteArrayUtils.toString(pom));
return pom;
}

一个很好的信息来源是 EFTlab website (他们的 BP-CCalc 工具可用于计算 key 、密码...)。

祝你好运!

关于cryptography - 密码版本 5 的方法 key 推导 (MKD),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42304386/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com