4

私は HSM と PKCS11 を使用してキー導出の問題に取り組んでいますが、現在、encrypt() メソッドを使用するのではなく、deliverKey() メソッドを使用するかどうかによって結果がまったく異なる理由を理解できません。どちらの場合も、結果に DESede/ECB/NoPadding アルゴリズムを使用しようとしていますが、結果を生成するために使用する方法 (deriveKey と暗号化) に応じて、異なる結果が表示されます。

少し戻って概要を説明します... Global Platform で使用される特定のキー導出方法を使用して、スマート カードで使用するマスター キーを多様化しています。このメソッドは、新しいキーを導出するために使用されるマスター キーと 8 バイトのデータ (多様化データ) から始まります。div データ バイトは文字通り、DESede/ECB/NoPadding を使用してマスター キーで暗号化され、その結果が新しい派生 3DES キーの一部として使用されます。(実際には、複数の暗号化が実行され、結果が連結されて新しい鍵が形成されますが、ここでは問題ではありません。)

両方のケースでマスター キーを検証し、多様化データが両方のケースで同じであることを検証し、同じパディングで同じアルゴリズムを使用していることを検証しました。また、派生キー テンプレートを DES、2DES、3DES に変更してみました。長さが異なるだけで、すべて同様の結果が得られます。

現在、IAIK ラッパー (Java で記述された pkcs11 ラッパー) を使用してテスト ケースを実装しました。これをここに投稿します。キーは単なるテスト キーであり、div データはサンプル div データであるため、ここには機密情報はありません。最初に HSM で基本キーを作成してから、多様化データを使用して session.deriveKey() を呼び出して新しいキーを派生させようとします。派生キーのバイトは 16 進数で出力されます (HSM 内ではなくメモリ内でキーを派生させる現在作業中の実装に基づいて、キーの値は正しくありません)。次に、マスター キーを使用して暗号化を実行するようにセッションを初期化し、多様化データを暗号化します。これにより、期待値が得られます (再び、動作中の実装に対してチェックされます)。

私が探しているのは、同じ基本キー、同じ div データ、および同じ暗号化アルゴリズムを使用しているときに、これらの操作が異なる結果をもたらす理由についての洞察です。私は、deriveKey() が水面下で何をしているのか理解できず、これを明らかにするためのドキュメントやソース コードを見つけることができません。派生キーは HSM の外では使用できないため、deliverKey() メソッドを使用できる必要があります。

任意の洞察をいただければ幸いです。

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 
4

1 に答える 1

8

DeriveKey を使用して HSM で生成されたキーと、session.encrypt() を使用して生成したキー バイトは、DES パリティのしくみを考慮すると、本質的に同じであることがわかります。

DES キーの各バイトの最下位ビットはパリティ ビットです。これは多くの実装では無視され、キーの一部としては使用されません。したがって、暗号化の結果にパリティ ビットを適切に設定すると、両方の結果が一致します。


0x3efe0eab6d3db397 <--- 正しい奇数パリティを持つ HSM 生成値

0x3fff0faa6c3cb297 <--- パリティ ビットが適切に設定されていない暗号化
結果

于 2013-01-22T23:29:33.243 に答える