HKDF是否在Java Cryptography Architecture中实现?

时间:2017-08-31 15:57:17

标签: java hmac hkdf

在我写的应用程序中,我需要使用HKDF从一个密码中导出两个不同的密钥。在Java中搜索有关如何使用它的示例我发现了这两个:

在这两种情况下,HKDF都是在JCA提供的HMAC之上实施的。我还没有详细阅读这些实现,但我想知道,这是不是在JCA或其自身的任何地方实现的?我是否必须实施自己的HKDF?

最让我担心的部分是在应用info参数时犯了一个错误。它看起来非常重要而且至关重要。

1 个答案:

答案 0 :(得分:8)

HKDF Java实现

不,Hashed Message Authentication Code (HMAC)-based key derivation function (HKDF)与大多数KDF一样,在JCA中没有标准实现。

其他项目中嵌入了一些实现(如您所说):

当然,还有Bouncy Castle使用他们自己的Hmac / Mac实现和API。然而,BC是一种巨大的依赖性,并且对于例如BC可能是不实用的。嵌入式或移动用例。为此,我实现了一个独立轻量级java lib(传递所有RFC 5869测试向量),它适用于任何javax.crypto.Mac实例:

如果您愿意,当使用内置的JCA Hmac实现时,您当然可以自己实现它,这是一个相当简单的规范。

HKDF的资讯参数

来自RFC 5869

  

虽然HKDF的定义中'info'值是可选的,但它是
  在应用程序中经常非常重要。其主要目标是   将派生的密钥材料绑定到特定于应用程序和上下文的中   信息。 (...)特别是,它可能会阻止推导   对于不同的背景,相同的密钥材料。

因此,例如,如果您想从相同的源材料派生密钥和IV,您将使用info参数(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));