PKCS11 deriveKey()和加密()返回的3DES不同的结果(PKCS11 deriveK

2019-08-07 17:09发布

我正在使用HSM PKCS11密钥导出问题,目前我不明白为什么我看到这取决于我是否使用deriveKey()方法,而不是使用encrypt()方法完全不同的结果。 在这两种情况下,我尝试使用DESede / ECB / NoPadding算法的结果,但具体取决于哪个方法(deriveKey与加密),我用它来生成结果,我看到不同的结果。

退一步了一会儿给予高度概括...我使用使用全球平台多样化使用的主密钥的智能卡上的特定密钥推导方法。 该方法开始于一个主密钥,并且用于导出新的密钥的8个字节数据(多元化数据)的。 在div数据字节被从字面上只是加密使用DESede / ECB / NoPadding主密钥,并将结果作为新的派生3DES密钥的一部分。 (实际上,有多种加密进行,结果连在一起,形成新的关键,但在这里不是问题。)

我已经验证了在两种情况下,主密钥,验证了多样化的数据是在两种情况下是相同的,验证了我使用的是相同的填充相同的算法。 我也试着改变导出密钥的模板DES,二维情感空间,3DES。 所有产生类似的结果,仅在长度不同。

目前我使用IAIK包装(用Java编写的PKCS11包装),我将张贴在这里实现我的测试用例。 最关键的是只是一个测试键和DIV数据样本格的数据,所以这里没有敏感信息。 我首先创建的HSM基地键,然后试图通过分散化数据调用session.deriveKey()派生新的密钥。 导出密钥字节被以十六进制(密钥值不正确,根据我的是导出密钥存储器代替HSM内当前正在执行)。 接着,我简单初始化使用主密钥来进行加密,然后将加密多元化数据的会话。 这就产生了预期值(再次,核对工作实现)。

我正在寻找的是任何了解为什么这些操作产生不同的结果,当我使用相同的基本键,同一div数据和相同的加密算法。 我不明白deriveKey()的表面下正在做,我无法找到任何文件或源代码,以摆脱对这个任何光线。 我必须能够使用deriveKey()方法,因为派生密钥将不可用的HSM之外。

任何见解表示赞赏。

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 

Answer 1:

事实证明,使用DeriveKey和我产生使用session.encrypt密钥字节()在HSM生成的密钥基本上是相同的如果考虑DES奇偶校验是如何工作的。

在DES密钥的每个字节的最低显著位是奇偶校验位,这是在许多实现忽略,不被用作关键字的一部分,因此,如果我正确设置我的加密结果,那么两个结果匹配的奇偶校验位。

0x3efe0eab6d3db397 <--- HSM生成的值与正确的奇校验
00111110 11111110 00001110 10101011 01101101 00111101 10110011 10010111

没有正确设置的奇偶校验位0x3fff0faa6c3cb297 <---加密结果
00111111 11111111 00001111 10101010 01101100 00111100 10110010 10010111



文章来源: PKCS11 deriveKey() and encrypt() returning different results for 3DES