Java PKCS11 deriveKey()和encrypt()为3DES返回不同的结果
我正在使用HSM和PKCS11解决一个密钥派生问题,目前我无法理解为什么我会看到完全不同的结果,这取决于我是否使用deriveKey()方法而不是encrypt()方法。在这两种情况下,我都试图对结果使用DESede/ECB/NoPadding算法,但根据生成结果所使用的方法(deriveKey与encrypt),我会看到不同的结果 退一步讲一讲,从高层次上概述一下。。。我正在使用Global Platform使用的特定密钥派生方法,使智能卡上使用的主密钥多样化。该方法从一个主密钥和8个字节的数据(数据)开始,用于派生新密钥。div数据字节实际上只是使用DESede/ECB/NoPadding使用主密钥加密,结果用作新派生的3DES密钥的一部分。(实际上,执行了多次加密,并将结果连接在一起以形成新密钥,但这不是这里的问题。) 我已经验证了两种情况下的主密钥,验证了两种情况下的多样化数据是相同的,验证了我使用的是具有相同填充的相同算法。我还尝试将派生密钥模板更改为DES、2DES、3DES。所有的结果都相似,只是长度不同 目前,我已经使用IAIK包装器(用Java编写的pkcs11包装器)实现了我的测试用例,我将在这里发布。密钥只是一个测试密钥,div数据是示例div数据,因此这里没有敏感信息。我首先在HSM中创建一个基键,然后尝试通过使用数据调用session.deriveKey()来派生一个新键。派生密钥字节以十六进制打印(根据我当前正在工作的在内存中而不是在HSM中派生密钥的实现,键值不正确)。接下来,我只需初始化会话,使用主密钥执行加密,然后加密数据。这将产生预期的值(再次根据工作实现进行检查) 我想了解的是,当我使用相同的基本密钥、相同的div数据和相同的加密算法时,为什么这些操作会产生不同的结果。我不明白deriveKey()在表面下做了什么,也找不到任何文档或源代码来阐明这一点。我必须能够使用deriveKey()方法,因为派生密钥在HSM之外不可用 任何见解都值得赞赏Java PKCS11 deriveKey()和encrypt()为3DES返回不同的结果,java,3des,pkcs#11,hsm,Java,3des,Pkcs#11,Hsm,我正在使用HSM和PKCS11解决一个密钥派生问题,目前我无法理解为什么我会看到完全不同的结果,这取决于我是否使用deriveKey()方法而不是encrypt()方法。在这两种情况下,我都试图对结果使用DESede/ECB/NoPadding算法,但根据生成结果所使用的方法(deriveKey与encrypt),我会看到不同的结果 退一步讲一讲,从高层次上概述一下。。。我正在使用Global Platform使用的特定密钥派生方法,使智能卡上使用的主密钥多样化。该方法从一个主密钥和8个字节的数
Mechanism keyGenerationMechanism = Mechanism.get(PKCS11Constants.CKM_DES3_KEY_GEN);
List supportedMechanisms = Arrays.asList(token.getMechanismList());
if (!supportedMechanisms.contains(Mechanism.get(PKCS11Constants.CKM_DES3_KEY_GEN))) {
output_.println("Mechanism not supported: DES3_KEY_GEN");
return;
}
// This is the master key that I want to diversify
DES3SecretKey baseKeyTemplate = new DES3SecretKey();
baseKeyTemplate.getValue().setByteArrayValue(new byte[] {0x3d, 0x20, 0x5b, 0x29, (byte) 0xfd, 0x04, (byte) 0xd9, (byte) 0x89, (byte) 0xd0, (byte) 0xfd, (byte) 0x85, (byte) 0xd5, (byte) 0xf7, (byte) 0xb3, 0x31, (byte) 0xd3,
0x3d, 0x20, 0x5b, 0x29, (byte) 0xfd, 0x04, (byte) 0xd9, (byte) 0x89});
baseKeyTemplate.getDerive().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getPrivate().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getSensitive().setBooleanValue(Boolean.FALSE);
baseKeyTemplate.getExtractable().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getLabel().setCharArrayValue("GP-3des-aba".toCharArray());
baseKeyTemplate.getObjectClass().setLongValue(PKCS11Constants.CKO_SECRET_KEY);
baseKeyTemplate.getKeyType().setLongValue(PKCS11Constants.CKK_DES3);
baseKeyTemplate.getEncrypt().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getDecrypt().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getWrap().setBooleanValue(Boolean.TRUE);
baseKeyTemplate.getUnwrap().setBooleanValue(Boolean.TRUE);
output_.println("baseKeyTemplate: " + baseKeyTemplate.toString());
SecretKey baseKey = (SecretKey) session.createObject(baseKeyTemplate);
System.out.println("Base key: ");
System.out.println(baseKey.toString());
output_
.println("################################################################################");
output_.println("derive key");
//DES3 Key Template
DESSecretKey derived3DESKeyTemplate = new DESSecretKey();
SecretKey derivedKeyTemplate = derived3DESKeyTemplate;
derivedKeyTemplate.getSensitive().setBooleanValue(Boolean.FALSE);
derivedKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getExtractable().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getPrivate().setBooleanValue(Boolean.FALSE);
derivedKeyTemplate.getKeyType().setLongValue(PKCS11Constants.CKK_DES);
// This represents the diversification data (.ie div bytes from some smart card)
byte[] data = new byte[] {0x00, (byte) 0x84, 0x30, (byte) 0x95, 0x35, 0x05,(byte) 0xf0, 0x01};
KeyDerivationStringDataParameters param = new KeyDerivationStringDataParameters(data);
Mechanism mechanism = Mechanism.get(PKCS11Constants.CKM_DES3_ECB);
if (!supportedMechanisms.contains(Mechanism
.get(PKCS11Constants.CKM_DES3_ECB))) {
output_.println("Mechanism not supported: CKM_DES3_ECB");
return;
}
mechanism.setParameters(param);
System.out.println("Derivation Mechanism: ");
output_.println(mechanism.toString());
output_
.println("--------------------------------------------------------------------------------");
Key derivedKey = session.deriveKey(mechanism, baseKey, derivedKeyTemplate);
if (derivedKey == null) {
output_.println("Found NO key that can be used for encryption.");
output_.flush();
System.exit(0);
}
System.out.println("Derived key: ");
output_.println(derivedKey.toString());
output_
.println("################################################################################");
output_.println("finished");
// initialize for encryption
Mechanism encryptionMechanism = Mechanism.get(PKCS11Constants.CKM_DES3_ECB);
session.encryptInit(encryptionMechanism, baseKey);
byte[] encryptedData = session.encrypt(data);
System.out.println("Encrypted data: " + new String(Hex.encodeHex(encryptedData)));
// This is the second part of the derived key, let's not worry about this yet since the first part isn't
// working.
// data = new byte[] {0x00, (byte) 0x84, 0x30, (byte) 0x95, 0x35, 0x05,(byte) 0x0f, 0x01,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//
// session.encryptInit(encryptionMechanism, baseKey);
// encryptedData = session.encrypt(data);
// System.out.println("Encrypted data: " + new String(Hex.encodeHex(encryptedData)));
session.closeSession();
pkcs11Module.finalize(null);
以下是我运行上述代码时的相关输出:
Base key:
Object Class: Secret Key
Token: true
Private: true
Modifiable: true
Label: GP-3des-aba
Key Type: DES3
ID: <NULL_PTR>
Start Date: 00.00.0000 (DD.MM.YYYY)
End Date: 00.00.0000 (DD.MM.YYYY)
Derive: true
Local: false
Key Generation Mechanism: <Information unavailable>
Allowed Mechanisms: <NULL_PTR>
Sensitive: false
Encrypt: true
Decrypt: true
Sign: false
Verify: false
Wrap: true
Unwrap: true
Extractable: true
Always Sensitive: false
Never Extractable: false
Check Value: <Attribute not present>
Wrap With Trusted: <Attribute not present>
Trusted: <Attribute not present>
Wrap Template: <Attribute not present>
Unwrap Template: <Attribute not present>
Value (hex): 3d205b29fd04d989d0fd85d5f7b331d33d205b29fd04d989
################################################################################
derive key
Derivation Mechanism:
Mechanism: CKM_DES3_ECB
Parameters:
String data (hex): 008430953505f001
--------------------------------------------------------------------------------
01/18/13 14:12:10 CALL: entering (in Java_iaik_pkcs_pkcs11_wrapper_PKCS11Implementation_C_1DeriveKey)
[snip]
Derived key:
Object Class: Secret Key
Token: true
Private: false
Modifiable: true
Label: <NULL_PTR>
Key Type: DES
ID: <NULL_PTR>
Start Date: 00.00.0000 (DD.MM.YYYY)
End Date: 00.00.0000 (DD.MM.YYYY)
Derive: false
Local: false
Key Generation Mechanism: CKM_DES3_ECB
Allowed Mechanisms: <NULL_PTR>
Sensitive: false
Encrypt: false
Decrypt: false
Sign: false
Verify: false
Wrap: false
Unwrap: false
Extractable: true
Always Sensitive: false
Never Extractable: false
Check Value: <Attribute not present>
Wrap With Trusted: <Attribute not present>
Trusted: <Attribute not present>
Wrap Template: <Attribute not present>
Unwrap Template: <Attribute not present>
Value (hex): 3efe0eab6d3db397 <--- call to deriveKey() value incorrect
################################################################################
finished
01/18/13 14:12:12 CALL: entering (in Java_iaik_pkcs_pkcs11_wrapper_PKCS11Implementation_C_1EncryptInit)
01/18/13 14:12:12 CALL: exiting (in Java_iaik_pkcs_pkcs11_wrapper_PKCS11Implementation_C_1EncryptInit)
01/18/13 14:12:12 CALL: entering (in Java_iaik_pkcs_pkcs11_wrapper_PKCS11Implementation_C_1Encrypt)
01/18/13 14:12:12 CALL: exiting (in Java_iaik_pkcs_pkcs11_wrapper_PKCS11Implementation_C_1Encrypt)
Encrypted data: 3fff0faa6c3cb297 <--- call to encrypt() returns the expected value
基本键:
对象类:密钥
令牌:对
二等兵:对
可修改:正确
标签:GP-3des-aba
密钥类型:DES3
身份证件:
开始日期:00.00.0000(年月日)
结束日期:00.00.0000(年月日)
推论:正确
本地:错
密钥生成机制:
允许的机制:
敏感:假
加密:真
解密:真
符号:假
验证:false
包装:对
展开:正确
可提取:正确
始终敏感:错误
不可提取:错误
检查值:
使用受信任的:
可信的:
包裹模板:
展开模板:
值(十六进制):3D205B29FD04D989D0FD85D5F7B33D205B29FD04D989
################################################################################
派生键
衍生机制:
机制:CKM_DES3_ECB
参数:
字符串数据(十六进制):008430953505f001
--------------------------------------------------------------------------------
2013年1月18日14:12:10调用:输入(在Java_iaik_pkcs_pkcs11_包装器_pkcs11实现_C_1DeriveKey中)
[剪报]
派生密钥:
对象类:密钥
令牌:对
二等兵:错
可修改:正确
标签:
密钥类型:DES
身份证件:
开始日期:00.00.0000(年月日)
结束日期:00.00.0000(年月日)
推论:错
本地:错
密钥生成机制:CKM_DES3_ECB
允许的机制:
敏感:假
加密:false
解密:false
符号:假
验证:false
包装:假
展开:假
可提取:正确
始终敏感:错误
不可提取:错误
检查值:
使用受信任的:
可信的:
包裹模板:
展开模板:
Value(hex):3efe0eab6d3db397如果考虑DES奇偶校验的工作方式,那么在HSM中使用DeriveKey生成的密钥和我使用session.encrypt()生成的密钥字节基本相同
DES密钥中每个字节的最低有效位是奇偶校验位,它在许多实现中被忽略,不作为密钥的一部分使用,因此,如果我在加密结果上正确设置奇偶校验位,则两个结果都匹配
0x3efe0eab6d3db397