当前位置: 首页 > 面试题库 >

PKCS11generateKey()和encrypt()返回3DES的不同结果

章嘉致
2023-03-14
问题内容

我正在使用HSM和PKCS11处理密钥派生问题,目前我无法理解为什么我会看到完全不同的结果,这取决于我是否使用generateKey()方法,而不是使用crypto()方法。在这两种情况下,我都尝试将DESede
/ ECB / NoPadding算法用于结果,但是根据我用来生成结果的方法(deriveKey与加密),我看到了不同的结果。

退后一会儿,以给出高层次的概述…我正在使用Global
Platform使用的特定密钥派生方法来使用于智能卡的主密钥多样化。该方法以主密钥和用于导出新密钥的8字节数据(多样化数据)开始。实际上,仅使用DESede
/ ECB /
NoPadding使用主密钥对div数据字节进行加密,并将结果用作新派生的3DES密钥的一部分。(实际上,执行了多次加密,并将结果串联在一起以形成新密钥,但这不是问题所在。)

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

目前,我已经使用IAIK包装器(用Java编写的pkcs11包装器)实现了我的测试用例,我将在此处发布它。该键只是一个测试键,而div数据是示例div数据,因此此处没有敏感信息。我首先在HSM中创建一个基本密钥,然后尝试通过使用多样化数据调用session.deriveKey()来派生新密钥。派生的密钥字节以十六进制打印(根据我当前正在工作的实现(在内存中而不是在HSM中派生密钥),密钥值不正确)。接下来,我简单地初始化会话以使用主密钥执行加密,然后加密多样化数据。这样就产生了预期值(再次对照有效的实施方案进行了检查)。

我要寻找的是对为什么当我使用相同的基本密钥,相同的div数据和相同的加密算法时,这些操作为何产生不同结果的任何见解。我不明白表面上的generateKey()在做什么,而且我找不到任何文档或源代码来阐明这一点。我必须能够使用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

问题答案:

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

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

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

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



 类似资料:
  • 我有以下问题。我的应用程序分为两部分:1)第一部分使用AES/CBC(Java)加密一些数据,2)第二部分必须检索数据并解密(Android)。要生成密钥,我使用以下代码 我的程序不需要不同的“源密钥”(字符串密码),但是只要源密钥相同,它就需要计算相同的密钥。不幸的是,程序的两部分生成的密钥不同,解密阶段失败。对如何解决这个问题有什么建议吗?

  • 当我浏览包含使用headless选项的产品的页面时,我会得到不同的结果 对于同一个问题,一次我得到的结果没有排序,另一次得到的结果排序正确。 Selenium firefox浏览器: 根据这篇帖子: “firefox在使用headless选项时不会发送不同的标题”。 如何使用无头选项从刮擦中获得恒定的结果? 更新: 原来,广告弹出窗口隐藏了价格排序菜单。通过设置DebanjanB发布的恒定窗口大小

  • 问题内容: 当我抓取包含使用无头选项产品的页面时,我得到不同的结果。 对于同一个问题,一次我得到未排序的结果,而另一次我得到正确的排序顺序。 Selenium firefox浏览器: 根据这篇文章: “ firefox使用无头选项时不会发送不同的头”。 如何使用无头选项从抓取中获得恒定的结果? 更新: 事实证明,广告弹出窗口隐藏了价格排序菜单。通过设置DebanjanB发布的恒定窗口大小,解决了问

  • 问题内容: 我正在运行以下MySQL查询,以查找没有手册(且车轮有黑轮等)的汽车 查询的结果看起来正确,但是它两次返回ID为27的汽车。如何更改查询,以使所有结果都是唯一的(没有重复项)? 问题答案: 假定这是唯一的主键,那么其中的一种联接将导致笛卡尔乘积。也就是说:或包含多个匹配项。 子查询通常是消除笛卡尔积的好工具。下面的示例查询显示了两种使用子查询的方法。 第一个子查询可确保我们只查看在20

  • 问题内容: 为什么更改总和顺序会返回不同的结果? = = 双方的Java和JavaScript的返回相同的结果。 我知道,由于以二进制表示浮点数的方式,某些有理数( 例如1/3-0.333333 … )无法精确表示。 为什么简单地更改元素的顺序会影响结果? 问题答案: 也许这个问题很愚蠢,但是为什么仅仅改变元素的顺序会影响结果呢? 它将根据值的大小更改四舍五入的点。作为示例 _样的_事情,我们所看

  • 为什么改变求和顺序会返回不同的结果? = Java和JavaScript都返回相同的结果。 我知道,由于浮点数在二进制中的表示方式,一些有理数(如1/3-0.333333...)不能精确表示。 为什么简单地改变元素的顺序会影响结果?