爪哇 - 如何生成专用密钥及公钥从密钥库开始(或.p12)

路易斯天使CARBONEL伊达尔戈:

生成与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;
    }
dave_thompson_085:

您的“公钥”实际上是一个证书(具体是X.509 v1或v3证书,根据您的OpenSSL的配置),其中包含一个公开,但是从公钥不同-是PEM格式,即使你已经误导命名它.der-和你的专用密钥进行加密。

除了使用PKCS12,罗伯托有效建议,通常是最简单的,因为它只有一个文件进行管理的方法仍然加密,因而更安全:

  • Java可以处理的X.509证书,但您使用CertificateFactory.getInstance("X.509"),并给它的InputStream,而不是KeyFactoryX509EncodedKeySpecCertificateFactory 可以处理PEM或DER,不像KeyFactory它只能处理DER,所以你不需要去PEM(带BEGIN / END / EOL和解码的base64)部分。

  • 标准的Java不能直接处理加密的密钥PKCS8。如果你可以添加第三方库,BouncyCastle的的bcpkix 可以这样做; 搜索十几现有Qs的是使用PEMParser(不PEMReader,那是旧版本)和JceOpenSSLPKCS8DecryptorBuilder否则,您可以添加-nodes到您的req -newkey -x509命令生成一个未加密的专用密钥文件,之后你去PEM它确实工作KeyFactoryPKCS8EncodedKeySpec(它仍然拼写-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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章