如何从秘密字符串中生成HMAC_SHA256密钥以在jose4j中与JWT一起使用?

时间:2015-08-14 09:06:36

标签: java encryption jwt jose4j

我想制作JWT并使用HMAC_SHA256签名。 对于该任务,我必须使用jose4j。 我试图根据秘密生成密钥:

SecretKeySpec key = new SecretKeySpec(("secret").getBytes("UTF-8"), AlgorithmIdentifiers.HMAC_SHA512);

但它会生成40位密钥,而使用HMAC_SHA256进行签名则需要512位密钥。

  • 主要问题 - 如何使用jose4j使用HMAC_SHA512签署令牌?
  • 上面的方法解决问题创建的问题 - 如何基于秘密字符串制作512位长密钥?

2 个答案:

答案 0 :(得分:13)

Section 3.2 of JWA / RFC 7518表示与哈希输出相同或更大的密钥必须与JWS HMAC SHA-2算法一起使用(即256位用于“HS256”,384bits /“HS384”和& ; 512位/“HS512”)。遵循IETF和NIST的建议通常是个好主意。粗略地说,HMAC的安全性来自散列输出的大小和密钥长度,以较小者为准。因此,使用“secret”字节作为密钥为您提供了一个只有48位长的密钥,实际上,它提供的安全性远远低于它,因为它是一个字典单词,无论HMAC SHA-2算法的强度如何选择。

默认情况下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);

答案 1 :(得分:5)

一种常见的方法是在将秘密用作签名密钥之前对其进行散列。

MessageDigest md = MessageDigest.getInstance("SHA-256");
String secret = "secret";
md.update(secret.getBytes("UTF-8"));
byte[] key = md.digest();

另一种方法是放宽关键长度的要求,例如:

JwtConsumer jwtConsumer = new JwtConsumerBuilder()
     .setVerificationKey(new HmacKey(secret.getBytes())) 
     .setRelaxVerificationKeyValidation() // allow shorter HMAC keys when used w/ HSxxx algs 
     .build();