生成与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
我保存在我的vault.keystore从wildfly: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);
任何人有任何想法有这种情况发生。提前致谢
对于我的生成JWT:
public ResteasyWebTarget getClientWebAgent(String host, String blockName) throws KeyStoreException
{
ResteasyClient clientBuilder = new ResteasyClientBuilder().establishConnectionTimeout(10, TimeUnit.SECONDS).socketTimeout(5, TimeUnit.SECONDS).build();
ResteasyWebTarget target = clientBuilder.target(host);
KeyPair keys = null;
try {
keys = keyStore.getKeys();
/*logger.infov(new String(Base64.getEncoder().encode(keys.getPrivate().getEncoded())));
logger.infov("****PUBLIC KEY ******");
logger.infov(new String(keys.getPublic().getEncoded()));*/
} catch (IOException e) {
logger.error(e);
}
Algorithm algorithm = Algorithm.RSA512((RSAPublicKey) keys.getPublic(), (RSAPrivateKey) keys.getPrivate());
Map<String, Object> headerClaims = new HashMap<>();
headerClaims.put("alg", "RS512");
headerClaims.put("typ", "JWT");
JWTCreator.Builder jwtCreator = JWT.create();
jwtCreator.withHeader(headerClaims);
jwtCreator.withIssuer(JWT_CLAIM_ISSUER);
jwtCreator.withIssuedAt(LocalDate.now().toDate());
jwtCreator.withExpiresAt(LocalDate.now().toDateTimeAtCurrentTime().plusSeconds(30).toDate());
String jwtToken = jwtCreator.sign(algorithm);
target.register(new BearerAuthenticator(jwtToken));
target.register(new LanguageHeaderToken(Locale.getDefault()));
return target;
}
您的“公钥”实际上是一个证书(具体是X.509 v1或v3证书,根据您的OpenSSL的配置),其中包含一个公开,但是从公钥不同-是PEM格式,即使你已经误导命名它.der
-和你的专用密钥进行加密。
除了使用PKCS12,罗伯托有效建议,通常是最简单的,因为它只有一个文件进行管理的方法和仍然加密,因而更安全:
Java可以处理的X.509证书,但您使用CertificateFactory.getInstance("X.509")
,并给它的InputStream
,而不是KeyFactory
和X509EncodedKeySpec
。CertificateFactory
可以处理PEM或DER,不像KeyFactory
它只能处理DER,所以你不需要去PEM(带BEGIN / END / EOL和解码的base64)部分。
标准的Java不能直接处理加密的密钥PKCS8。如果你可以添加第三方库,BouncyCastle的的bcpkix 可以这样做; 搜索十几现有Qs的是使用PEMParser
(不PEMReader
,那是旧版本)和JceOpenSSLPKCS8DecryptorBuilder
。否则,您可以添加-nodes
到您的req -newkey -x509
命令生成一个未加密的专用密钥文件,之后你去PEM它确实工作KeyFactory
有PKCS8EncodedKeySpec
。(它仍然拼写-nodes
使用的过程中手段的未加密的专用密钥文件,即使没有它使用的加密一直没有平原又名单DES几十年了。)您的系统上的任何入侵者或恶意软件,可以读取该文件能得到您的专用密钥,这在许多情况下是有风险的。
最后,如果你真的只想要密钥对,而不是一个证书,不打扰req -newkey -x509
。而是使用openssl genpkey
生成的专用密钥,或上了年纪,但简单的openssl genrsa -nodes
后面(或管道输送到),openssl pkcs8 -topk8 -nocrypt
将其转换为PKCS8未加密格式。然后使用openssl pkey -pubout
或旧openssl rsa -pubout
作与公钥一个单独的文件。这些命令可以写(读回如果适用)DER格式而不是PEM; 如果你这样做,你的代码不需要去PEM的步骤,你可以通过二进制文件的内容KeyFactory
。对未加密的文件的风险是与上面相同。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句