我目前正在为3个未来的项目开发一个身份验证服务器。这个想法是,身份验证服务器使用私钥签名并创建访问令牌,并且未来的3个项目将具有公钥来验证访问令牌。
我以pem格式生成了rsa密钥:
openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -pubout -outform PEM -out public.pem
然后我在线阅读了Java无法读取这些格式的信息。所以我将它们转换为DER格式:
openssl pkcs8 -topk8 -inform PEM -outform DER -in private.pem -out private.der -nocrypt
openssl rsa -pubin -inform PEM -in public.pem -outform DER -out public-der
然后,我可以使用私钥创建并签署访问令牌,如下所示:
try (InputStream privateKeyStream = Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream("jwt/private.der"))) {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyStream.readAllBytes());
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = kf.generatePrivate(keySpec);
String jwt = Jwts.builder()
.signWith(privateKey, SignatureAlgorithm.RS512)
.setHeaderParam("typ", SecurityConstants.TOKEN_TYPE)
.setIssuer(SecurityConstants.TOKEN_ISSUER)
.setAudience(SecurityConstants.TOKEN_AUDIENCE)
.setSubject(uuid.toString())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.claim("rol", Arrays.asList(ERole.TRIAL.name()))
.compact();
return jwt;
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
throw new AccessTokenCreationFailedException("Could not create access token!");
}
现在我需要在使用令牌时对其进行验证。这是我所走的路:
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyStream.readAllBytes());
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(keySpec); // Throws exception
Jwts.parser()
.setSigningKey(publicKey)
.parseClaimsJws(token.replace(SecurityConstants.TOKEN_PREFIX, ""));
这会抛出java.security.InvalidKeyException: Missing key encoding
这让我感到困惑,如何使用不同的关键规格,哪些不可用。无论如何,我现在如何使用公共密钥验证令牌?我的密钥格式错误吗?如果是这样,我在重新创建密钥方面没有问题,对此将特别感谢特定的openssl命令。