加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – PKCS11 deriveKey()和encrypt()返回3DES的不同结果

发布时间:2020-12-15 08:49:50 所属栏目:Java 来源:网络整理
导读:我正在使用HSM和PKCS11处理密钥派生问题,目前我无法理解为什么我看到完全不同的结果取决于我是否使用deriveKey()方法而不是使用encrypt()方法.在这两种情况下,我都试图使用DESede / ECB / NoPadding算法来获得结果,但是根据我用来生成结果的方法(deriveKey与
我正在使用HSM和PKCS11处理密钥派生问题,目前我无法理解为什么我看到完全不同的结果取决于我是否使用deriveKey()方法而不是使用encrypt()方法.在这两种情况下,我都试图使用DESede / ECB / NoPadding算法来获得结果,但是根据我用来生成结果的方法(deriveKey与加密),我看到了不同的结果.

退一步以提供高级概述……我正在使用Global Platform使用的特定密钥派生方法来使用于智能卡的主密钥多样化.该方法以主密钥和用于导出新密钥的8字节数据(多样化数据)开始. div数据字节实际上只是使用DESede / ECB / NoPadding用主密钥加密,结果用作新导出的3DES密钥的一部分. (实际上,执行了多次加密,并将结果连接在一起形成新密钥,但这不是问题.)

我在两种情况下都验证了主密钥,验证了两种情况下的多样化数据是相同的,验证我使用相同的算法和相同的填充.我也尝试将派生密钥模板更改为DES,2DES,3DES.所有产生的结果都相似,只是长度不同.

目前我已经使用IAIK包装器(用Java编写的pkcs11包装器)实现了我的测试用例,我将在此处发布.密钥只是一个测试密钥,div数据是样本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) 0x85,(byte) 0xd5,(byte) 0xf7,(byte) 0xb3,0x31,(byte) 0xd3,0x3d,(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)  0x0f,0x01,//                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

解决方法

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

DES密钥中每个字节的最低有效位是奇偶校验位,在许多实现中被忽略,并且不用作密钥的一部分,因此如果我在加密结果上正确设置奇偶校验位,则两个结果都匹配.

0x3efe0eab6d3db397< --- HSM生成的值具有正确的奇校验
00222220 22222110 00001110 10101011 01101101 00111101 10110011 10010111

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读