java 如何从秘密字符串制作 HMAC_SHA256 密钥以在 jose4j 中与 JWT 一起使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32006323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make HMAC_SHA256 key from secret string to use it with JWT in jose4j?
提问by foki
I want to produce JWTs and sign them with HMAC_SHA256. For that task I must use jose4j. I have tried to generate key based on secret with:
我想生成 JWT 并使用 HMAC_SHA256 对其进行签名。对于那个任务,我必须使用jose4j。我试图根据秘密生成密钥:
SecretKeySpec key = new SecretKeySpec(("secret").getBytes("UTF-8"), AlgorithmIdentifiers.HMAC_SHA512);
but it generates 40bits key while 512bit one is required for signing using HMAC_SHA256.
但它生成 40 位密钥,而使用 HMAC_SHA256 签名需要 512 位密钥。
- The primary issue - how to sign tokens with HMAC_SHA512 using jose4j?
- Issue created by my approach solving issue above - how to make 512bit long secret key based on secret string?
- 主要问题 - 如何使用 jose4j 使用 HMAC_SHA512 签署令牌?
- 由我解决上述问题的方法创建的问题 - 如何根据秘密字符串制作 512 位长的秘密密钥?
回答by Brian Campbell
Section 3.2 of JWA / RFC 7518says that a key of the same size as the hash output or larger must be used with the JWS HMAC SHA-2 algorithms (i.e, 256 bits for "HS256", 384bits/"HS384", & 512 bits/"HS512"). It's generally a good idea to follow this advice from the IETF and NIST. Roughly speaking the security of an HMAC comes from the size of the hash output and the key length, whichever is smaller. So using the bytes of "secret" as the key gives you a key that's only 48 bits long and, in practice, provides considerably less security than even that because it's a dictionary word, regardless of the strength of the HMAC SHA-2 algorithm you chose.
JWA / RFC 7518 的第 3.2 节指出,必须将与散列输出大小相同或更大的密钥与 JWS HMAC SHA-2 算法一起使用(即,“HS256”为 256 位、384 位/“HS384”和 512位/“HS512”)。遵循 IETF 和 NIST 的建议通常是个好主意。粗略地说,HMAC 的安全性来自散列输出的大小和密钥长度,以较小者为准。因此,使用“secret”字节作为密钥可为您提供一个只有 48 位长的密钥,并且实际上提供的安全性甚至比这要低得多,因为它是字典单词,无论您使用的 HMAC SHA-2 算法的强度如何选择了。
By default jose4jenforces the minimum key sizes mandated by JWA/RFC 7518. However, as Hans points out, there are ways to tell jose4j to relax the key length requirement. This can be done with JwtConsumer
by calling .setRelaxVerificationKeyValidation()
on JwtConsumerBuilder
and on JsonWebSignature
directly with .setDoKeyValidation(false)
. Below is a quick example producing and consuming a JWT using HMAC SHA256 that shows both.
默认情况下,jose4j强制执行 JWA/RFC 7518 规定的最小密钥大小。然而,正如 Hans 指出的那样,有一些方法可以告诉 jose4j 放宽密钥长度要求。这是可以做到的JwtConsumer
调用 .setRelaxVerificationKeyValidation()
上JwtConsumerBuilder
和JsonWebSignature
直接.setDoKeyValidation(false)
。下面是一个使用 HMAC SHA256 生成和使用 JWT 的快速示例,其中显示了两者。
JwtClaims claims = new JwtClaims();
claims.setExpirationTimeMinutesInTheFuture(5);
claims.setSubject("foki");
claims.setIssuer("the issuer");
claims.setAudience("the audience");
String secret = "secret";
Key key = new HmacKey(secret.getBytes("UTF-8"));
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(claims.toJson());
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
jws.setKey(key);
jws.setDoKeyValidation(false); // relaxes the key length requirement
String jwt = jws.getCompactSerialization();
System.out.println(jwt);
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime()
.setAllowedClockSkewInSeconds(30)
.setRequireSubject()
.setExpectedIssuer("the issuer")
.setExpectedAudience("the audience")
.setVerificationKey(key)
.setRelaxVerificationKeyValidation() // relaxes key length requirement
.build();
JwtClaims processedClaims = jwtConsumer.processToClaims(jwt);
System.out.println(processedClaims);
回答by Hans Z.
A common approach is to hash the secret before using it as a signing key.
一种常见的方法是在将密钥用作签名密钥之前对其进行散列。
MessageDigest md = MessageDigest.getInstance("SHA-256");
String secret = "secret";
md.update(secret.getBytes("UTF-8"));
byte[] key = md.digest();
The alternative is to relax the requirement on the key length with something like:
另一种方法是放宽对密钥长度的要求,例如:
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setVerificationKey(new HmacKey(secret.getBytes()))
.setRelaxVerificationKeyValidation() // allow shorter HMAC keys when used w/ HSxxx algs
.build();