如何使用 RSA512 算法创建签名的 JWT

Posted

技术标签:

【中文标题】如何使用 RSA512 算法创建签名的 JWT【英文标题】:How to create a signed JWT with RSA512 algorithm 【发布时间】:2019-11-20 04:03:53 【问题描述】:

我试图创建 JWT(“JOT”)令牌以使我的 api 调用真实。当我尝试使用 RSA512 签名创建令牌时,我会收到一条错误消息

java.lang.IllegalArgumentException:必须使用 RSA PrivateKey 计算 RSA 签名。 javax.crypto.spec.SecretKeySpec 类型的指定密钥不是 RSA PrivateKey。

我正在使用以下代码:

 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS512;

 long nowMillis = System.currentTimeMillis();
  Date now = new Date(nowMillis);
 byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET_KEY);
 Key signingKey = new SecretKeySpec(apiKeySecretBytes, 
                signatureAlgorithm.getJcaName());

   JwtBuilder builder = Jwts.builder().claim("uuid", 
    id).setIssuedAt(now).setExpiration(new Date(600000))
    .signWith(signatureAlgorithm, signingKey);

注意:我的“SECRET_KEY”是一个字符串,是一个在线随机生成的私钥。 我的问题是如何从以 RSA 密钥大小编码为 4096 的字符串中获取 Key 对象。 4096,因为我使用的是RSA512加密,建议RSA512使用4096密钥

【问题讨论】:

要在jwt.io 上验证您的令牌,您必须在verify signature - your-256-bit-secret 下的右栏中提供您的密码 该错误说明了密钥类型,但您没有显示有关 SECRET_KEY 的详细信息。你能把钥匙贴出来吗? 我使用了一些随机密钥,例如“adsfd564464gfasdf45ds4dffas56f4asd6fda45fads” 对于 HS 密钥来说已经足够了,但肯定不是 RSA 密钥。 RSA 密钥如下所示:-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDHikastc8+I81zCg/qWW8dMr8mqvXQ3qbPAmu0RjxoZVI47tvs...5vg087ZngKfFGR5rozDiTsK5DceTV97K a3Y+Nzl+XWTxDBWk4YPh2ZlKv402hZEfWBYxUDn5ZkH/bw== -----END RSA PRIVATE KEY----- 在此 site 上,您可以创建用于测试的密钥。 感谢@jsp 的信息,它有效,但看起来我没有提供正确的签名。 ,我能够生成,但仍然显示 Invalid Signature @ jwt.io 【参考方案1】:

最初我没有提供 Base64 编码的 RSAkey,我将其再次编码为 base64 ,这是我收到此错误的原因。

java.lang.IllegalArgumentException:必须使用 RSA PrivateKey 计算 RSA 签名。 javax.crypto.spec.SecretKeySpec 类型的指定密钥不是 RSA PrivateKey。

当我提供 RSAKey base 64 编码或字节码私钥时,我又回到了错误之下

只能为 HMAC 签名指定 Base64 编码的密钥字节。如果使用 RSA 或椭圆曲线,请改用 signWith(SignatureAlgorithm, Key) 方法。

当我提供一个字符串/字节的私钥时,它一直在检查 HMAC 算法。请参阅下面来自 JWTBuilder 的代码。

@Override
public JwtBuilder signWith(SignatureAlgorithm alg, byte[] secretKey) 
    Assert.notNull(alg, "SignatureAlgorithm cannot be null.");
    Assert.notEmpty(secretKey, "secret key byte array cannot be null or empty.");
    Assert.isTrue(alg.isHmac(), "Key bytes may only be specified for HMAC signatures.  If using RSA or Elliptic Curve, use the signWith(SignatureAlgorithm, Key) method instead.");
    this.algorithm = alg;
    this.keyBytes = secretKey;
    return this;


@Override
public JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey) 
    Assert.hasText(base64EncodedSecretKey, "base64-encoded secret key cannot be null or empty.");
    Assert.isTrue(alg.isHmac(), "Base64-encoded key bytes may only be specified for HMAC signatures.  If using RSA or Elliptic Curve, use the signWith(SignatureAlgorithm, Key) method instead.");
    byte[] bytes = TextCodec.BASE64.decode(base64EncodedSecretKey);
    return signWith(alg, bytes);


@Override
public JwtBuilder signWith(SignatureAlgorithm alg, Key key) 
    Assert.notNull(alg, "SignatureAlgorithm cannot be null.");
    Assert.notNull(key, "Key argument cannot be null.");
    this.algorithm = alg;
    this.key = key;
    return this;

提供 java.security.key 类型的私钥始终是最好的主意,并且必须是 RSA 密钥。我使用 P12 证书加载私钥。

【讨论】:

以上是关于如何使用 RSA512 算法创建签名的 JWT的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 RSA256 算法生成 JWT 签名?

如何在自定义绑定的 defaultAlgorithmSuite 中使用 RSA-SHA512 作为签名算法?

Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:RSA(RS512) 签名 JWT

如何使用 RSA 私钥解密 JWT

HMAC 256 与 HMAC 512 JWT 签名加密

使用 System.IdentityModel.Tokens.Jwt 使用 RS512 验证 JWT 签名