- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发用于 EMV 交易的软件,但我面临着雇佣我的公司的文档严重缺乏的问题。
其中之一是关于用于生成 ARQC 的 MKD(在第一个 GENERATE AC 期间)。我从消息请求中知道IAD如下:
0FA501A030F8000000000000000000000F000000000000000000000000000000
最佳答案
(在 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:
- 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.
- 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.
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.
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;
}
关于cryptography - 密码版本 5 的方法 key 推导 (MKD),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42304386/
我是一名新的 Windows 8 开发人员,我有一些代码是为 Linux 设计的,但只要安装了 GTK# 也可以在 Windows 上运行。 我目前正在将该应用程序作为现代 UI (Metro) 应用
我正在尝试通过本文之后的证书身份验证来获取 saml token How to pass a certificate to WSTrust to get Saml Token 当我像这样调用电话时出现
大多数签名证书足迹都是 20 字节长(Windows 证书管理器中的字段“足迹”)。 这怎么可能是颁发(认证)机构签署的值?具体来说,证书的签名应该是由私钥签名的证书字段的哈希值,因此至少具有颁发者私
有没有办法证明,我的意思是技术上和法律上证明,一段代码已经在计算机上的特定时间运行? 我认为这可以通过涉及校验和和可信时间戳等加密技术来实现,您怎么看? 最佳答案 技术上,问题是您是否为这项任务事先准
我用公钥加密数据,用私钥解密数据。 是否可以用一个公钥拥有多个私钥? 最佳答案 不,你不能,这是公私钥加密的本质。为什么你想要一个公钥有多个私钥?如果您想签署加密文件怎么办?如果这可能的话,我将能够将
数字签名取决于消息和 key 。假设接收方多次复制消息(我们唯一 ID 的原因),为什么签名会不同(因为消息和 key 相同)? 最佳答案 比特币使用 ECDSA,同一消息和 key 的签名不同的原因
PKC 有问题 考虑以下场景 当发送者需要向接收者发送消息时: sender 使用receiver's Public Key生成密文 receiver 使用receivers 私钥解密密文。 所以我的
如果您有以下形式的椭圆曲线: y^2 = x^3 + a*x + b (mod p) 有没有好的程序来计算这条曲线上的点数? 我已经阅读了 Schoof 和 Schoof-Elkies-Atkin
我需要创建一个一次性填充板来加密一些数据(大小为几KB)。我应该如何生成一次一次性填充,以避免与诸如rand()之类的基本随机数生成相关的所有伪随机问题? 我是否可以使用现有的,受信任的工具或库? 最
谁能提出一个工具包或框架(或一个想法),该工具包或框架(或构想)可用于在没有受信任的第三方服务器的情况下实现安全且防欺诈的在线扑克(德州扑克)客户端吗? 最佳答案 您要问的是所谓的mental pok
我经营一个网站,我们将某些帐户标记为骗子,并“标记”他们的帐户和所有使用的信用卡都是坏的。我们不存储实际的信用卡值,而是存储它的校验和/MD5 算法。 我们现在一直在碰撞。存储这些值的最佳方法是什么
散列函数中的多重碰撞与第一或第二原像之间有什么区别。 第一次原像攻击:给定一个散列 h,找到一条消息 m,使得 哈希(m) = h。 第二个原像攻击:给定一个固定的消息 m1,找到一个不同的消息 m2
当我听说破解加密算法的方法时,我注意到通常关注如何非常快速地解密以及如何减少搜索空间。但是,我总是想知道如何识别成功的解密,以及为什么这不会形成瓶颈。还是通常假设加密/解密对是已知的? 最佳答案 来自
我看到了一个通过以下步骤生成 AES key 的代码片段: 生成一个 16 字节的随机值数组。 SecureRandom random = new SecureRandom(); byte[] key
你好 我有一个长度为 n 的二进制字符串。我的目标是字符串中的所有位都等于“1”。 我可以翻转我想要的字符串的每一位,但在翻转字符串的位后,它会进行随机循环移位。(移位长度均匀分布在 0...n-1
当A发送数据到 B通过使用公钥加密的网络连接,A 如何达到认证、保密的目标 ? 最佳答案 在这种情况下,A 使用 B 的公钥,B 使用 A 的公钥。 secret 性:如果 A 使用 B 的公钥加密某
在挑战-响应机制(和其他系统)中,建议不要使用基于时间的随机数。 为什么应该避免? 最佳答案 (免责声明:我没有加密货币学位,我写的一切只是外行的意见。) 不鼓励使用基于时间的随机数,因为它们很可能偶
消息摘要用于验证消息是否是预期消息。 将散列摘要与内容捆绑在一起以形成消息会增加多少碰撞和原像攻击消息的难度? 例如编码: message = data . hash1(data) message_h
我想知道是否可以对大多数英特尔芯片中存在的 TPM ( http://en.wikipedia.org/wiki/Trusted_Platform_Module ) 进行编程,以便: - decide
在关于 Block Cipher Modes 的维基百科文章中他们有一个整洁的小图表 未加密的镜像、使用 ECB 模式加密的同一镜像以及使用其他方法加密的同一镜像的另一个版本。 在大学时,我开发了自己
我是一名优秀的程序员,十分优秀!