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.
You should be using
CKM_DES3_ECB_ENCRYPT_DATA
instead ofCKM_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.