Java中的HKDF实现
不,与大多数 KDF 一样,基于散列消息验证码 (HMAC) 的密钥派生函数 ( HKDF) 在 JCA 中没有标准实现(截至 2020 年)。
其他项目中嵌入了一些实现(就像您已经说过的那样):
当然,还有使用自己的 Hmac/Mac 实现和 API 的Bouncy Castle 。然而,BC 是一个巨大的依赖项,对于嵌入式或移动用例来说可能是不切实际的。为此,我实现了一个独立的轻量级 java 库(通过所有 RFC 5869 测试向量),它适用于任何javax.crypto.Mac
实例:
如果您愿意,当然可以自己实现它,当使用内置的 JCA Hmac 实现时,这是一个相当简单的规范。
HKDF 中的信息参数
来自RFC 5869:
虽然“info”值在 HKDF 的定义中是可选的,但它
在应用程序中通常非常重要。它的主要目标是
将派生的密钥材料绑定到应用程序和上下文特定的
信息。(...) 特别是,它可能会阻止为不同的上下文派生相同的密钥材料。
因此,例如,如果您想从相同的源材料中派生密钥和 IV,您将使用 info 参数(使用此库):
//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));