无法使用 jsonwebtoken 创建 RS256 jwt 密钥

Failing to create a RS256 jwt key using jsonwebtoken

我正在尝试按照本教程创建我的 JWT: https://developer.okta.com/blog/2018/10/31/jwts-with-java 但是当我将 SignatureAlgorithm 从 HS256 更改为 RS 256 时,我收到以下错误:

The signing key's algorithm 'SHA256withRSA' does not equal a valid HmacSHA* algorithm name and cannot be used with HS512.

这是负责 Jwt 的代码部分:

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET_KEY);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        JwtBuilder builder = Jwts.builder().setId(id)
                .setIssuedAt(now)
                .setSubject(subject)
                .setIssuer(issuer)
                .signWith(signingKey);

我使用 SECRET_KEY 例如:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCtrKVnwse4anfX+JzM7imShXZUC+QBXQ11A5bOWwHFkXc4nTfE
Or3fJjnRSU5A3IROFU/pVVNiXJNkl7qQZK5mYb8j3NgqX8zZJG7IwLJ/Pm2sRW5Q
j32C/uJum64Q/iEIsCg/mJjDLh1lylEMEuzKgTdWtoeLfxDBL2AJ20qXzQIDAQAB
AoGBAKNXi0GpmjnCOPDxLFg5bvQVfhLSFCGMKQny1DVEtsfgZmbixv5R2R41T4+d
CHJMdEsUFFJ6I7CRLTcg1SDU8IhcAWCBRSNeVuomCHlQG16ti8HxwhiwIcjvDz/z
NC2sL5ZJ2eJnhbtXLdf6pxxO1pA5vLp1AX06IaETO977XvupAkEA+ZgtGZybyUkf
tEA3ekXc5eLoW+zgU0C1fATWcIZ8Iq5YV1BW+3oAzf8HgIbkQh4LM2qa6An3l+vW
NXR4wICHkwJBALIhrcdJqKw36qiyenq+m78klp5SnurQifVt0Sy1GMWyOUqYz5jK
t9sGo9Qn6GDuYe/XGXKWQW25PkEYXxxPPx8CQQCpICyvRidp5VrOURVGjUB5pZ+9
am02/In9V2nXJcnH1kuWHqJSFQGmlEEJHl5dTu5YEMyWnupezzd/UUThbDZxAkAz
TNO5QxNalbf04YG4e9Bq2eSur+iog2pXzkqhb3404UDypNOUkz0jzOO9o8ieschu
xCnGAFPTf7fYE2bAxmnNAkEA0/3bdsvJclquypqP9CQeQnxGwQtWz6+yn07gj3U1
V19mdeKCUZWklRarrcr67u9DdEx+JowyEY/ppzgeQtW01g==
-----END RSA PRIVATE KEY-----

我的猜测是我签署了错误的密钥... 但我不确定我需要做什么..

您尝试使用的密钥不是您的代码可以使用的 PKCS#8 格式。你有两个选择。

  1. 将您的 RSA 密钥保存到 pr_test.key 文件并使用命令 openssl pkcs8 -topk8 -in pr_test.key -out pr_test_pkcs8.key -nocrypt 转换它。然后复制粘贴到你的SECRET_KEY variable.You 还需要稍微修改一下代码:
        StringBuilder pkcs8Lines = new StringBuilder();
        BufferedReader rdr = new BufferedReader(new StringReader(SECRET_KEY2));
        String line;
        while ((line = rdr.readLine()) != null) {
            pkcs8Lines.append(line);
        }
        String pkcs8Pem = pkcs8Lines.toString();
        pkcs8Pem = pkcs8Pem.replace("-----BEGIN PRIVATE KEY-----", "");
        pkcs8Pem = pkcs8Pem.replace("-----END PRIVATE KEY-----", "");
        pkcs8Pem = pkcs8Pem.replaceAll("\s+","");

        byte[] valueDecoded = Base64.decodeBase64(pkcs8Pem);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(valueDecoded);
        KeyFactory rsaFact = KeyFactory.getInstance("RSA");
        RSAPrivateKey key = (RSAPrivateKey) rsaFact.generatePrivate(keySpec);

        JwtBuilder builder = Jwts.builder().setId("ID")
                .setIssuedAt(new Date())
                .setSubject("Subject")
                .setIssuer("Issuer")
                .signWith(SignatureAlgorithm.RS256, key);
        return builder.compact();
  1. 第二种选择是使用 bouncycastle 库,它允许您使用任何类型的密钥格式:
package com.example.demo;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.springframework.stereotype.Service;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;


@Service
public class JWTService {

    private static String SECRET_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" +
            "MIICXgIBAAKBgQCtrKVnwse4anfX+JzM7imShXZUC+QBXQ11A5bOWwHFkXc4nTfE\n" +
            "Or3fJjnRSU5A3IROFU/pVVNiXJNkl7qQZK5mYb8j3NgqX8zZJG7IwLJ/Pm2sRW5Q\n" +
            "j32C/uJum64Q/iEIsCg/mJjDLh1lylEMEuzKgTdWtoeLfxDBL2AJ20qXzQIDAQAB\n" +
            "AoGBAKNXi0GpmjnCOPDxLFg5bvQVfhLSFCGMKQny1DVEtsfgZmbixv5R2R41T4+d\n" +
            "CHJMdEsUFFJ6I7CRLTcg1SDU8IhcAWCBRSNeVuomCHlQG16ti8HxwhiwIcjvDz/z\n" +
            "NC2sL5ZJ2eJnhbtXLdf6pxxO1pA5vLp1AX06IaETO977XvupAkEA+ZgtGZybyUkf\n" +
            "tEA3ekXc5eLoW+zgU0C1fATWcIZ8Iq5YV1BW+3oAzf8HgIbkQh4LM2qa6An3l+vW\n" +
            "NXR4wICHkwJBALIhrcdJqKw36qiyenq+m78klp5SnurQifVt0Sy1GMWyOUqYz5jK\n" +
            "t9sGo9Qn6GDuYe/XGXKWQW25PkEYXxxPPx8CQQCpICyvRidp5VrOURVGjUB5pZ+9\n" +
            "am02/In9V2nXJcnH1kuWHqJSFQGmlEEJHl5dTu5YEMyWnupezzd/UUThbDZxAkAz\n" +
            "TNO5QxNalbf04YG4e9Bq2eSur+iog2pXzkqhb3404UDypNOUkz0jzOO9o8ieschu\n" +
            "xCnGAFPTf7fYE2bAxmnNAkEA0/3bdsvJclquypqP9CQeQnxGwQtWz6+yn07gj3U1\n" +
            "V19mdeKCUZWklRarrcr67u9DdEx+JowyEY/ppzgeQtW01g==\n" +
            "-----END RSA PRIVATE KEY-----";


    public String generateToken() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
        java.security.Security.addProvider(
                new org.bouncycastle.jce.provider.BouncyCastleProvider()
        );
        PemReader pemReader = new PemReader(new StringReader(SECRET_KEY));

        PemObject pemObject;
        pemObject = pemReader.readPemObject();

        KeyFactory factory = KeyFactory.getInstance("RSA");
        byte[] content = pemObject.getContent();
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
        RSAPrivateKey privateKey = (RSAPrivateKey) factory.generatePrivate(privKeySpec);

        JwtBuilder builder = Jwts.builder().setId("ID")
                .setIssuedAt(new Date())
                .setSubject("Subject")
                .setIssuer("Issuer")
                .signWith(SignatureAlgorithm.RS256, privateKey);
        return builder.compact();
    }
}

build.gradle 需要的依赖项:

  implementation 'org.bouncycastle:bcprov-jdk15on:1.64'
  implementation 'org.bouncycastle:bcpkix-jdk15on:1.64'