问题描述
在我写的应用程序中,我需要使用HKDF从一个密码中获取两个不同的密钥。在Java中搜索如何使用它的示例我发现了这两个:
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:
- https://github.com/WhisperSystems/libsignal-protocol-java/blob/master/java/src/main/java/org/whispersystems/libsignal/kdf/HKDF.java
- https://www.javatips.net/api/keywhiz-master/hkdf/src/main/java/keywhiz/hkdf/Hkdf.java
在这两种情况下,HKDF都已实施在JCA提供的HMAC之上。我还没有详细阅读这些实现,但我想知道,这是不是在JCA或其自身的任何地方实现的?我是否必须实施自己的HKDF?
In both cases HKDF is implemented on top of the HMAC provided by JCA. I haven't read those implementations in detail yet but I was wondering, is this not implemented anywhere in JCA or itself? Do I have to implement my own HKDF?
最让我担心的部分是在应用info参数时出错。它看起来非常重要和关键。
The part that worries me the most, is making a mistake in applying the info argument. It looks non-trivial and critical.
推荐答案
HKDF Java实现
不,
- mozilla-services/sync-crypto
- WhisperSystems/libsignal-protocol-java
- square/keywhiz
当然,还有使用自己的Hmac / Mac实现和API。然而,BC是一种巨大的依赖性,并且对于例如BC可能是不实用的。嵌入式或移动用例。为此,我实现了一个独立,轻量级java lib(传递所有RFC 5869测试向量),它适用于任何实例:
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
如果您愿意,您当然可以自行实施,这是一个相当直接的规范,当使用内置的JCA Hmac实现时。
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.
来自:
所以例如,如果您想从相同的源材料派生密钥和IV,您将使用info参数():
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));
这篇关于HKDF是否在Java Cryptography Architecture中实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!