Я пытаюсь понять Jason Web Token с парами открытого ключа и закрытого ключа RSA. Я сгенерировал пары ключей RSA, используя эти сайты - https://travistidwell.com/jsencrypt/demo/, и сохранил их в двух разных файлах - закрытый ключ "my_key" имеет вид
-----BEGIN RSA PRIVATE KEY-----
MIICWgIBAAKBgFrSlpibGae4QZjcQp20b9+go22JF9WHJU4TLfdwJbumIgHlukD9
S/W7Dr1j4AXtJ0yJopdnf0bY4294SjjMO4DFHrLDEAB8ZeZkMhfyparYWKHECV5e
szvR6dIHGeDc1CoJolAsPmpO+0qfK4LfkesmLu+diIy9I+B2KJAAka6hAgMBAAEC
gYAlsQuqnYOSJVej1pUW2dEr34CzbpejmAiVVERZUgN20sV+QBaB7hzeCBlf49kO
3JLYoq4FY4BgqJYKpsM2uxteIC8dLJdayyNze1mnPiPW3wLR2bzedOJdjcY0H3Ju
M7lZlk9NVnBI7PNXw4hanifCGY2XPKyrOwrqrMgFsC382QJBAKlKAErRU9N8LZgq
TNAhMTaTPvpZuK4LqqV8RCqPFuNz1tVsO/cjGHfrU3R1pM619K6xCUjvwYvXL0MM
6vm/CKsCQQCJV6/bFuc4L+Uyik0Q+zaRz3fKi5h/AWoN1vmBcXQ01F5GtTAlZDc6
lk/rBk4M69k899I95ReMlIfc68S51P3jAkAp5eLEoaI5iVZPfsicClr/wtmnZGVM
zh5h7quATQHBMX5OPAdrVwhLRbbV7/fmISp5wd8mahBg59UOpzfQr/MZAkAtgC9y
lhPkOXnlVIxTo+ZgSCuXnsfWy9Em5KGkkMG+/tx88GoS+TCS6Flxs5UIEtrVqASv
HMbAfDTGrBVwu2+hAkAnrAHRhFlC8O9zAhoFkWcaYeFu+y1pBcF3pzFfQBpn6uK8
Xd0Ln+eMNaYl6lAECG36jtUvnKLkyfWMHzqdkERj
-----END RSA PRIVATE KEY-----
открытый ключ "my_key.pub" как
-----BEGIN PUBLIC KEY-----
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgFrSlpibGae4QZjcQp20b9+go22J
F9WHJU4TLfdwJbumIgHlukD9S/W7Dr1j4AXtJ0yJopdnf0bY4294SjjMO4DFHrLD
EAB8ZeZkMhfyparYWKHECV5eszvR6dIHGeDc1CoJolAsPmpO+0qfK4LfkesmLu+d
iIy9I+B2KJAAka6hAgMBAAE=
-----END PUBLIC KEY-----
Когда я использую этот ключ в NodeJS как -
var fs = require('fs');
var JWT = require('jsonwebtoken');
var privateKey = fs.readFileSync('./my_key', 'utf8');
var publicKey = fs.readFileSync('./my_key.pub', 'utf8');
var jwtOptions = {
issuer : 'Chittaranjan Sardar',
subject: 'JWT Cross Platforms',
audience: 'https://github.com/crsardar',
expiresIn: '5m',
algorithm: "RS256"
};
let token = JWT.sign({user: 'CRSARDAR'}, privateKey, jwtOptions);
console.log("generated token = " + token);
var verifyResult = JWT.verify(token, publicKey, jwtOptions);
console.log("Verification has passed : " + JSON.stringify(verifyResult));
Работает нормально.
Но когда я пытаюсь использовать в Java,следующим образом -
package com.crsardar.handson.java.springboot.jwt.controller;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JWTJavaWithPublicPrivateKey
{
public static void main(String[] args)
{
System.out.println("generating keys");
Map<String, Object> rsaKeys = null;
try
{
rsaKeys = getRSAKeys();
}
catch (Exception e)
{
e.printStackTrace();
}
PublicKey publicKey = (PublicKey) rsaKeys.get("public");
PrivateKey privateKey = (PrivateKey) rsaKeys.get("private");
System.out.println("generated keys");
String token = generateToken(privateKey);
System.out.println("Generated Token:\n" + token);
verifyToken(token, publicKey);
}
public static String generateToken(PrivateKey privateKey)
{
String token = null;
try
{
Instant now = Instant.now();
Instant after = now.plus(Duration.ofMinutes(1));
Date date = Date.from(after);
Claims claims = Jwts.claims();
claims.put("user", "CRSARDAR");
claims.put("issuer", "Chittaranjan Sardar");
claims.put("subject", "JWT Cross Platforms");
claims.put("audience", "https://github.com/crsardar");
claims.put("created", new Date());
JwtBuilder jwtBuilder = Jwts.builder();
jwtBuilder.setClaims(claims);
jwtBuilder.setExpiration(date);
jwtBuilder.signWith(SignatureAlgorithm.RS512, privateKey);
token = jwtBuilder.compact();
}
catch (Exception e)
{
e.printStackTrace();
}
return token;
}
// verify and get claims using public key
private static Claims verifyToken(String token, PublicKey publicKey)
{
Claims claims;
try
{
JwtParser jwtParser = Jwts.parser();
jwtParser.setSigningKey(publicKey);
Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
claims = claimsJws.getBody();
System.out.println("verifyToken : issuer = " + claims.get("issuer"));
}
catch (Exception e)
{
claims = null;
}
return claims;
}
private static Map<String, Object> getRSAKeys() throws Exception
{
Map<String, Object> keys = new HashMap();
PrivateKey privateKey = getPrivateKey();
PublicKey publicKey = getPublicKey();
keys.put("private", privateKey);
keys.put("public", publicKey);
return keys;
}
private static PrivateKey getPrivateKey() throws Exception
{
ClassLoader classLoader = JWTJavaWithPublicPrivateKey.class.getClassLoader();
URL resource = classLoader.getResource("my_key");
File file = new File(resource.getFile());
byte[] keyBytes = Files.readAllBytes(Paths.get(file.toURI()));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(spec);
}
private static PublicKey getPublicKey() throws Exception
{
ClassLoader classLoader = JWTJavaWithPublicPrivateKey.class.getClassLoader();
URL resource = classLoader.getResource("my_key.pub");
File file = new File(resource.getFile());
byte[] keyBytes = Files.readAllBytes(Paths.get(file.toURI()));
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
}
Это дает мне следующие ошибки -
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
at com.crsardar.handson.java.springboot.jwt.controller.JWTJavaWithPublicPrivateKey.getPrivateKey(JWTJavaWithPublicPrivateKey.java:126)
at com.crsardar.handson.java.springboot.jwt.controller.JWTJavaWithPublicPrivateKey.getRSAKeys(JWTJavaWithPublicPrivateKey.java:110)
at com.crsardar.handson.java.springboot.jwt.controller.JWTJavaWithPublicPrivateKey.main(JWTJavaWithPublicPrivateKey.java:35)
Caused by: java.security.InvalidKeyException: invalid key format
at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:331)
at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:357)
at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91)
at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)
at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316)
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213)