【问题标题】:How to make HMAC_SHA256 key from secret string to use it with JWT in jose4j?如何从秘密字符串中制作 HMAC_SHA256 密钥以在 jose4j 中将其与 JWT 一起使用?
【发布时间】:2015-11-07 11:44:15
【问题描述】:

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

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

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

  • 主要问题 - 如何使用 jose4j 使用 HMAC_SHA512 签署令牌?
  • 我的方法解决上述问题所产生的问题 - 如何根据密钥字符串制作 512 位长的密钥?

【问题讨论】:

    标签: java encryption jwt jose4j


    【解决方案1】:

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

    默认情况下jose4j 强制执行 JWA/RFC 7518 规定的最小密钥长度。但是,正如 Hans 指出的,有一些方法可以告诉 jose4j 放宽密钥长度要求。这可以通过在JwtConsumerBuilderJsonWebSignature 上直接使用.setDoKeyValidation(false) 调用.setRelaxVerificationKeyValidation() 来使用JwtConsumer 来完成。下面是一个使用 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);
    

    【讨论】:

      【解决方案2】:

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

      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();
      

      【讨论】:

        【解决方案3】:

        为了安全起见,“秘密”作为密钥太短且不安全。 您可以使用以下代码生成一个安全的密钥作为您的个人密钥。

        //Generating a safe HS256 Secret key
        SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        String secretString = Encoders.BASE64.encode(key.getEncoded());
        logger.info("Secret key: " + secretString);
        

        【讨论】:

          猜你喜欢
          • 2020-08-12
          • 2019-03-17
          • 1970-01-01
          • 1970-01-01
          • 2020-07-08
          • 2021-08-27
          • 2010-11-22
          • 2023-01-20
          • 2019-03-21
          相关资源
          最近更新 更多