Java 使用公钥解码和验证JWS令牌

Java 使用公钥解码和验证JWS令牌,java,encryption,jwt,base64,jjwt,Java,Encryption,Jwt,Base64,Jjwt,我们需要处理来自API网关的请求。用户的身份将通过JWT令牌传递给我们并进行加密(通过私钥),我们将收到公钥(在Base64中)以验证它 现在我一直没能做到这一点。 我所做的是使用自行生成的私钥/公钥加密并再次验证我自己的令牌: KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); kp = kpg.generateKeyPair(); //generate &am

我们需要处理来自API网关的请求。用户的身份将通过JWT令牌传递给我们并进行加密(通过私钥),我们将收到公钥(在Base64中)以验证它

现在我一直没能做到这一点。 我所做的是使用自行生成的私钥/公钥加密并再次验证我自己的令牌:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
kp = kpg.generateKeyPair();

//generate & sign simple token:
Map<String, Object> claims = new HashMap<>();
claims.put("id", "xxx");
claims.put("role", "user");
token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.RS256, kp.getPrivate()).compact();

//now sign the thing
Claims claims = Jwts.parser().setSigningKey(kp.getPublicKey()).parseClaimsJws(base64EncodedToken).getBody();
System.out.println(claims.get("id")); //gives me xxx as expected
然后,不再使用KeyPairGenerator,而是通过从(Base64)文件读取公钥/私钥并对其进行解码来创建公钥/私钥:

public PrivateKey getPrivateKey() throws Exception {
    String base64PrivateKey = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("private.key").toURI())));
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec (Base64.getDecoder().decode(base64PrivateKey.getBytes()));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePrivate(keySpec);
}

public PublicKey getPublicKey() throws Exception {
    String base64PublicKey = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("public.key").toURI())));
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePublic(keySpec);
}

当我再次运行相同的过程时(生成加密令牌并验证它):

线程“main”io.jsonwebtoken.SignatureException中出现异常:JWT签名与本地计算的签名不匹配。无法断言JWT有效性,不应信任JWT有效性

我肯定遗漏了什么,因为我对加密几乎没有经验

另外,文件如下所示:

public.key:miibijanbgkqhkig9w0baqefaocaq8amiibcgkcaqeaxetc3258

private.key:MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEA


为了避免混淆,请注意:“解密”意味着加密,但您的源代码使用的是“签名**”。(JWS)签名的验证必须使用公钥完成,而签名本身则使用私钥完成。是否确实要使用相同的密钥对进行签名/验证?(如前所述,请不要混合签名和加密)@MichaelFehr感谢您纠正我的错误;“取消签名”的正确术语是什么“验证”并没有完全涵盖这一点。关于您的代码:您使用FileWriter(“key.pub”)编写公钥,但使用ClassLoader.getSystemResource(“public.key”)读取(另一个?)密钥。如果是另一个文件,它将解释错误。第二:JWT使用公钥进行验证。数据本身通常不是加密的,而是用Base64Url编码的,因此您可以将其命名为Base64UrlDecoding;很抱歉给你带来了混乱
public PrivateKey getPrivateKey() throws Exception {
    String base64PrivateKey = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("private.key").toURI())));
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec (Base64.getDecoder().decode(base64PrivateKey.getBytes()));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePrivate(keySpec);
}

public PublicKey getPublicKey() throws Exception {
    String base64PublicKey = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("public.key").toURI())));
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePublic(keySpec);
}