PKCS11generateKey每次返回不同的值

时间:2019-09-17 21:29:54

标签: encryption smartcard pkcs#11 hsm cryptoki

我有一个主密钥,并且想要使其多样化/派生为其他密钥(在HSM内部)。遵循this answer之后,我得到了以下代码:

final java.security.Key key = token.getKeyStore().getKey(baseKeyAlias, null);
iaik.pkcs.pkcs11.objects.Key baseKey = ((iaik.pkcs.pkcs11.provider.keys.IAIKPKCS11SecretKey) key).getKeyObject();

DESSecretKey derived3DESKeyTemplate = new DESSecretKey();
SecretKey derivedKeyTemplate = derived3DESKeyTemplate;
derivedKeyTemplate.getLabel().setCharArrayValue(derivedKeyAlias.toCharArray());
derivedKeyTemplate.getId().setByteArrayValue(derivedKeyAlias.getBytes());
derivedKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getKeyType().setLongValue(PKCS11Constants.CKK_DES2);
derivedKeyTemplate.getEncrypt().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getDecrypt().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getWrap().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getUnwrap().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getDerive().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getExtractable().setBooleanValue(Boolean.TRUE);
derivedKeyTemplate.getPrivate().setBooleanValue(Boolean.FALSE);
derivedKeyTemplate.getSign().setBooleanValue(Boolean.TRUE);

byte[] derivationData = DatatypeConverter.parseHexBinary("45525448555200749916");
KeyDerivationStringDataParameters param = new KeyDerivationStringDataParameters(derivationData);
Mechanism mechanism = new Mechanism(PKCS11Constants.CKM_DES3_ECB);
mechanism.setParameters(param);
final Key deriveKey = session.deriveKey(mechanism, baseKey, derivedKeyTemplate);
System.out.println("deriveKey successful!");        

您可以看到我正在使用PKCS#11包装器(IAIK)。问题在于推导使用相同的推导数据生成不同的密钥。这是预期的行为吗?

我认为每次导出的密钥都是不同的,因为我正在用此密钥加密一个已知值,并且每次的结果都不同:

byte[] data = DatatypeConverter.parseHexBinary("01020304050607080C7D8B973D588B478000000000000000");
Mechanism m = new Mechanism(PKCS11Constants.CKM_DES3_ECB);
session.encryptInit(m, deriveKey);
byte[] bytes;
bytes = session.encrypt(data);
System.out.println(DatatypeConverter.printHexBinary(bytes));

首次进行密钥派生和值加密

deriveKey successful!
encrypt using deriveKey: 7C4BB979F26FC78831CC83AB378E7B1D8E2F2D73B140D25D

第二次密钥派生和值加密

deriveKey successful!
encrypt using deriveKey: F1CE8649333EA10E63B13DB3733CD55FFB010A63C6CEC7F2

第三次密钥派生和价值设定

deriveKey successful!
encrypt using deriveKey: A8D801BC1C0142B9E77576AEA0FBE677915E47144B6DCF3C

据我所知,派生是使用基本密钥对数据(派生数据)进行加密。然后,该加密值将转换为另一个密钥(派生密钥),因此,如果派生数据和基本密钥相同,则该值应该相同。this answer解释了此步骤。

1 个答案:

答案 0 :(得分:0)

您应该使用CKM_DES3_ECB_ENCRYPT_DATA而不是CKM_DES3_ECB

奇怪的是您没有收到错误消息,因为CKM_DES3_ECB不应用于密钥派生(请参阅PKCS#11 v2.40中的表68)。

您的假设是正确的-此密钥派生算法必须为相同的派生数据(和主密钥)提供相同的密钥。

祝您的项目好运!


请注意:您的示例派生数据似乎具有固定的结构。这样(在ECB模式下使用DES)生成的DES密钥的第三部分将始终是相同的(即8000000000000000的加密)。您可能需要先对派生数据(例如使用SHA-256)进行哈希处理,然后再将其用于密钥派生。或完全重新考虑此算法。

免责声明:我不是加密专家,所以请确认我的想法。