Is HKDF implemented in Java Cryptography Architecture?

前端 未结 1 1225
小鲜肉
小鲜肉 2021-02-06 10:25

In the application I\'m writing I need to do HKDF to derive two different keys from one password. Searching for examples on how to it in Java I found these two:

  • ht
1条回答
  •  无人及你
    2021-02-06 11:08

    HKDF Implementations in Java

    No, Hashed Message Authentication Code (HMAC)-based key derivation function (HKDF) has, like most KDFs, no standard implementation in JCA (as of 2020).

    There are some implementations embedded in other projects (like you already said):

    • mozilla-services/sync-crypto
    • WhisperSystems/libsignal-protocol-java
    • square/keywhiz

    Also there is, of course, Bouncy Castle which use their own Hmac/Mac implementations and APIs. BC is however a massive dependency, and may be unpractical for e.g. embedded or mobile use case. For this I implemented a standalone, lightweight java lib (passing all of the RFC 5869 test vectors), which works with any javax.crypto.Mac instance:

    • https://github.com/patrickfav/hkdf

    If you prefer, you could, of course implement it on your own, it's a fairly straight forward spec, when using the built-in JCA Hmac implementation.

    Info Parameter in HKDF

    From the RFC 5869:

    While the 'info' value is optional in the definition of HKDF, it is
    often of great importance in applications. Its main objective is to
    bind the derived key material to application- and context-specific
    information. (...) In particular, it may prevent the derivation of the same keying material for different contexts.

    So for example if you want to derive an Secret Key and IV from the same source material you would use the info parameter (using this lib):

    //example input
    String userInput = "this is a user input with bad entropy";
    
    HKDF hkdf = HKDF.fromHmacSha256();
    
    //extract the "raw" data to create output with concentrated entropy
    byte[] pseudoRandomKey = hkdf.extract(staticSalt32Byte, userInput.getBytes(StandardCharsets.UTF_8));
    
    //create expanded bytes for e.g. AES secret key and IV
    byte[] expandedAesKey = hkdf.expand(pseudoRandomKey, "aes-key".getBytes(StandardCharsets.UTF_8), 16);
    byte[] expandedIv = hkdf.expand(pseudoRandomKey, "aes-iv".getBytes(StandardCharsets.UTF_8), 16);
    
    //Example boilerplate encrypting a simple string with created key/iv
    SecretKey key = new SecretKeySpec(expandedAesKey, "AES"); //AES-128 key
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(expandedIv));
    byte[] encrypted = cipher.doFinal("my secret message".getBytes(StandardCharsets.UTF_8));
    

    0 讨论(0)
提交回复
热议问题