PKCS11 deriveKey returning different values every time

599 Views Asked by At

I have a master key and want to diversify/derive it into other keys (inside an HSM). After following this answer I have this code:

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!");        

As you can see I am using a PKCS#11 wrapper (IAIK). The problem is the derivation generating different keys with the same derivation data. Is this an expected behaviour?

I think the derived keys are different each time because I am encrypting a known value with this key and the results are different every time:

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));

first run of key derivation and value encription

deriveKey successful!
encrypt using deriveKey: 7C4BB979F26FC78831CC83AB378E7B1D8E2F2D73B140D25D

second run of key derivation and value encription

deriveKey successful!
encrypt using deriveKey: F1CE8649333EA10E63B13DB3733CD55FFB010A63C6CEC7F2

third run of key derivation and value encription

deriveKey successful!
encrypt using deriveKey: A8D801BC1C0142B9E77576AEA0FBE677915E47144B6DCF3C

As far as I know the derivation is the encryption of data (derivation data) with a base key. This encrypted value is then converted to another key (derived key) and thus this value should be the same if the derivation data and base key are the same, this answer explain this steps.

1

There are 1 best solutions below

0
On

You should be using CKM_DES3_ECB_ENCRYPT_DATA instead of CKM_DES3_ECB.

It is strange that you are not getting an error as CKM_DES3_ECB should not be allowed for key derivation (see table 68 in PKCS#11 v2.40).

Your presumptions are correct -- this key derivation algorithm must give the same key for the same derivation data (and master key).

Good luck with your project!


Just a note: Your example derivation data seem to have a fixed structure. This way (using DES in ECB mode) the third part of resulting DES key would be always the same (i.e. encryption of 8000000000000000). You might want to hash the derivation data (e.g. with SHA-256) before it is used for key derivation. Or completely re-consider this algorithm.

Disclaimer: I am no crypto expert so please do validate my thoughts.