正如标题所说,我正在尝试解密来自启用DUKPT的扫描仪的DUKPT加密曲目数据。
我拥有DUKPT的ANSI标准(X9.24),并成功实现了从KSN和BDK生成IPEK的能力。此外,我已成功实现了通过对PIN加密密钥进行异或来生成左和右MAC请求和响应密钥的功能。最后,我能够生成EPB。
从这里,我不明白如何从我生成的L / R键生成MAC请求和响应。
最后,一旦我走到那一步,接下来会发生什么?我什么时候才能获得解密由启用DUKPT的设备发送的曲目数据的密钥?
我知道Thales模拟器和jPOS。我的代码目前正在引用Thales Simulator来完成它的所有工作。但是,文件解密过程并没有返回预期的数据。
如果有人能够提供解密跟踪数据的一些见解,我们将非常感激。
答案 0 :(得分:35)
我花了太多时间研究可怕的X9.24规范,最后让加密和解密工作与我的供应商的例子和营销迅速决定切换供应商。既然它是一个标准,你会认为任何人的实现都是一样的。我希望。无论如何,事情的实施方式各不相同。你必须研究细则,以确保你的工作与你的另一面相同。
但这不是你的问题。
首先,如果您需要从信用卡解密数据轨道,您可能有兴趣生成一个密钥,该密钥将根据原始的超级秘密Base Derivation Key解密数据。这与MAC生成无关,只是在那个可怕的规范中提到。如果在HSM的完整密钥序列号的计数器部分中设置了位,则需要为该密钥序列号和设备ID生成IPEK并重复应用规范中的“不可逆密钥生成过程”。
我的代码部分如下所示:(很抱歉在帖子中列出了很长的内容。)
/*
* Bit "zero" set (this is a 21 bit register)(ANSI counts from the left)
* This will be used to test each bit of the encryption counter
* to decide when to find another key.
*/
testBit=0x00100000;
/*
* We have to "encrypt" the IPEK repeatedly to find the current key
* (See Section A.3). Each time we encrypt (generate a new key),
* we need to use the all prior bits to the left of the current bit.
* The Spec says we will have a maximum of ten bits set at any time
* so we should not have to generate more than ten keys to find the
* current encryption key.
*/
cumBits=0;
/*
* For each of the 21 possible key bits,
* if it is set, we need to OR that bit into the cumulative bit
* variable and set that as the KSN count and "encrypt" again.
* The encryption we are using the goofy ANSI Key Generation
* subroutine from page 50.
*/
for(int ii=0; ii<21; ii++)
{
if( (keyNumber&testBit) != 0)
{
char ksr[10];
char eightByte[8]={0};
cumBits |= testBit;
ksn.count=cumBits; /* all bits processed to date */
memcpy(ksr, &ksn,10); /* copy bit structure to char array*/
memcpy(crypt,&ksr[2],8); /* copy bytes 2 through 9 */
/*
* Generate the new Key overwriting the old.
* This will apply the "Non-reversible Key Generation Process"
* to the lower 64 bits of the KSN.
*/
keyGen(&key, &crypt, &key);
}
testBit>>=1;
}
其中 keyNumber是来自ksn的当前计数器 ksn是一个80位结构,包含来自HSM的80位密钥序列号 crypt是一个64位的数据块,因为我使用的是openSSL,所以它的类型为DES_cblock。 key是128位双DES_cblock结构。 keyGen例程几乎是从规范第50页的“不可逆密钥生成过程”本地子例程中逐字记录。
在此结束时,密钥变量将包含几乎可用于解密的密钥。编写规范的那些家伙在关键词上添加了一些“变体”行为,让我们保持警惕。如果密钥用于解密数据流(如信用卡磁道),则需要使用0xFF对XOR字节5和13进行异或,并且三重DES自身加密密钥(ECB模式)。我的代码如下:
DOUBLE_KEY keyCopy;
char *p;
p=(char*)&key;
p[ 5]^=0xff;
p[13]^=0xff;
keyCopy=key;
des3(&keyCopy, (DES_cblock *)&key.left, &key.left);
des3(&keyCopy, (DES_cblock *)&key.right, &key.right);
如果您使用它来解密PIN块,则需要使用0xFF对字节7和15进行异或。 (我不是100%确定这不应该也适用于流模式,但是我的供应商将其排除在外。)
如果是PIN块,则在ECB模式下使用3-DES加密。如果它是数据流,它将在CBC模式下加密,初始化矢量为零。
(我提到过我不太关心规范吗?)有趣的是,如果服务器端(上图)记得并拒绝,加密端可用于非硬件防篡改安全模块以前使用过的密钥。这项技术非常整洁。 ANSI规范还有待改进,但技术还可以。
祝你好运。 / Bob Bryan答案 1 :(得分:3)
对于数据加密,变量为0000000000FF0000.0000000000FF0000
,因此您需要XOR字节5和13而不是7和15.此外,您需要对每个关键部分(左右)进行额外的3DES自加密步骤)。
以下是jPOS中的相关代码 https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java#L1843-1856