使用OpenSSL生成一些密钥,然后在Base64中对其进行编码并获取它们,并尝试生成它们以验证JWT的身份验证。这是我发生的事情的代码和描述使用以下命令生成:
openssl req -x509 -newkey rsa:4096 -keyout private_key.pem -out public_key.der
openssl pkcs12 -export -out keyStore.p12 -inkey private_key.pem -in public_key.der
base64 –w 0 private_key.pem > private_key_base64_enc.txt
base64 –w 0 public_key.der > public_key_base64_enc.txt
我从wildfly保存在vault.keystore中:private_key_base64_enc.txt和public_key_base64_enc.txt
然后在我的java类中,我写了以下内容:
private void jwtSignedAuthentication(String token, PropName vaultBlockName) throws Exception
{
String rsa512Alias = vaultBlockName.getDefaultValue();
String rsa512pvt = VaultReader.getValue(rsa512Alias, "privateKey");
String rsa512pbc = VaultReader.getValue(rsa512Alias, "publicKey");
KeyFactory keyfatc = null;
PrivateKey privateKey = null;
PublicKey publicKey = null;
try {
keyfatc = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
logger.error(e);
}
StringBuilder pkcs8Lines = new StringBuilder();
BufferedReader rdr = new BufferedReader(new StringReader(new String(Base64.getDecoder().decode(rsa512pvt.getBytes()))));
String line;
while ((line = rdr.readLine()) != null) {
pkcs8Lines.append(line);
}
// Remove the "BEGIN" and "END" lines, as well as any whitespace
String pkcs8Pem = pkcs8Lines.toString();
pkcs8Pem = pkcs8Pem.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
pkcs8Pem = pkcs8Pem.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
pkcs8Pem = pkcs8Pem.replaceAll("\\s+","");
byte[] dataPvt = Base64.getDecoder().decode(pkcs8Pem.getBytes());
PKCS8EncodedKeySpec specPvt = new PKCS8EncodedKeySpec(dataPvt);
byte[] dataPbc = Base64.getDecoder().decode(rsa512pbc.getBytes());
StringBuilder publicLinesBuilder = new StringBuilder();
BufferedReader readerPlubKey = new BufferedReader(new StringReader(new String(dataPbc)));
String lineP;
while ((lineP = readerPlubKey.readLine()) != null) {
publicLinesBuilder.append(lineP);
}
String pubK = publicLinesBuilder.toString();
pubK = pubK.replace("-----BEGIN CERTIFICATE-----", "");
pubK = pubK.replace("-----END CERTIFICATE-----", "");
pubK = pubK.replaceAll("\\s+","");
X509EncodedKeySpec specPbc = new X509EncodedKeySpec(Base64.getDecoder().decode(pubK.getBytes()));
try {
privateKey = keyfatc.generatePrivate(specPvt);
publicKey = keyfatc.generatePublic(specPbc);
} catch (InvalidKeySpecException e) {
logger.error(e);
}
Algorithm algorithm = Algorithm.RSA512((RSAPublicKey) publicKey, (RSAPrivateKey) privateKey);
// Creación de un verificador JWT
JWTVerifier verifier = JWT.require(algorithm).withIssuer(JWT_CLAIM_ISSUER).acceptLeeway(2).build();
UserContext userContext = new UserContext();
userContext.setUserName(JWT_CLAIM_ISSUER);
try {
// Decode JWT, verificación del token.
@SuppressWarnings("unused")
DecodedJWT decodeJwt = verifier.verify(token);
} catch (JWTDecodeException e) {
logger.error(e);
}
}
[当我尝试生成密钥时,我返回null:
privateKey = keyfatc.generatePrivate(specPvt);
publicKey = keyfatc.generatePublic(specPbc);
任何人都不知道这会发生什么。在此先感谢
也许您是在没有分配有效别名的情况下生成密钥库的,请查看您的命令,您没有使用-name
选项。该命令应如下所示:
openssl pkcs12 -export -out keyStore.p12 -inkey private_key.pem -in public_key.der -name "alias"
在Java中使用键的更聪明的方法是创建KeyPair
:
KeyPair loadKeyPair() throws Exception {
// Read keystore from resource folder
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL resource = classLoader.getResource("keyStore.p12");
File file = new File(Objects.requireNonNull(resource).toURI());
char[] keyPass = "1234".toCharArray();
String alias = "alias";
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
try (FileInputStream is = new FileInputStream(file)) {
keystore.load(is, keyPass);
}
Key key = keystore.getKey(alias, keyPass);
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
return new KeyPair(publicKey, (PrivateKey) key);
}
return null;
}
然后从密钥对中提取RSAPublicKey
和RSAPrivateKey
键:
void loadKeys() throws Exception{
KeyPair keyPair = loadKeyPair();
if (null != keyPair) {
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
}
}
希望您的Json Web令牌对您有所帮助,并祝您好运! :-p
您的“公钥”实际上是一个证书(具体是X.509 v1或v3证书,具体取决于您的openssl配置),它包含一个公钥,但不同于公钥,并且是PEM格式即使您误导了它的名称.der
-并且您的私钥已加密。
除了使用PKCS12的方法外,正如Roberto所建议的那样,并且通常是最简单的,因为它仅是一个要管理的文件,并且仍然是加密的,因此更加安全: can can 真正
] >CertificateFactory.getInstance("X.509")
并给它一个InputStream
而不是KeyFactory
和X509EncodedKeySpec
。CertificateFactory
KeyFactory
只能处理DER的方式不同,因此您不需要de-PEM(条形BEGIN / END / EOL和对base64进行解码)。PEMParser
(不是PEMReader
,这是较早的版本)和JceOpenSSLPKCS8DecryptorBuilder
的十几个现有Q。否则,您可以将-nodes
添加到req -newkey -x509
命令中以生成未加密KeyFactory
中与PKCS8EncodedKeySpec
一起使用。 (即使数十年来,即使没有加密也没有使用过单一的DES,它仍然拼写为-nodes
。)当然,使用未加密的私钥文件意味着系统上可以读取该文件的任何入侵者或恶意软件都可以将其获取。私钥,在很多情况下是有风险的。req -newkey -x509
。取而代之的是使用openssl genpkey
生成私钥,或者使用更旧但更简单的openssl genrsa -nodes
跟随openssl pkcs8 -topk8 -nocrypt
将其转换为PKCS8非加密格式。然后使用openssl pkey -pubout
或更旧的openssl rsa -pubout
来用公共密钥制作一个单独的文件。这些命令可以写(和在适用时回读)DER格式而不是PEM。如果这样做,您的代码不需要de-PEM步骤,您只需将二进制文件内容传递给KeyFactory
。未加密文件的风险与上面相同。