PKCS11 deriveKey каждый раз возвращает разные значения
У меня есть главный ключ, и я хочу преобразовать его в другие ключи (внутри HSM). После этого ответа у меня есть этот код:
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
Насколько мне известно, производным является шифрование данных (производных данных) с помощью базового ключа. Это зашифрованное значение затем преобразуется в другой ключ (производный ключ), и, следовательно, это значение должно быть таким же, если производные данные и базовый ключ совпадают, этот ответ объясняет эти шаги.
1 ответ
Вы должны использовать CKM_DES3_ECB_ENCRYPT_DATA
вместо того CKM_DES3_ECB
.
Странно, что вы не получаете сообщение об ошибке CKM_DES3_ECB
не должно допускаться для получения ключа (см. таблицу 68 в PKCS#11 v2.40).
Ваши предположения верны - этот алгоритм деривации ключей должен давать один и тот же ключ для тех же данных деривации (и мастер-ключ).
Удачи тебе с твоим проектом!
Просто примечание: данные вашего примера деривации, похоже, имеют фиксированную структуру. Таким образом (с использованием DES в режиме ECB) третья часть результирующего ключа DES всегда будет одинаковой (т. Е. Шифрование8000000000000000
). Возможно, вы захотите хешировать производные данные (например, с помощью SHA-256), прежде чем они будут использоваться для получения ключей. Или полностью пересмотреть этот алгоритм.
Отказ от ответственности: я не эксперт по криптографии, поэтому, пожалуйста, подтвердите мои мысли.