java-如何从密钥库(.p12)开始生成PrivateKey和PublicKey

问题描述 投票:1回答:2

使用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);

任何人都不知道这会发生什么。在此先感谢

java private-key pkcs#12 pkcs#8
2个回答
0
投票

也许您是在没有分配有效别名的情况下生成密钥库的,请查看您的命令,您没有使用-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;
}

然后从密钥对中提取RSAPublicKeyRSAPrivateKey键:

void loadKeys() throws Exception{
    KeyPair keyPair = loadKeyPair();

    if (null != keyPair) {
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
    }
}

希望您的Json Web令牌对您有所帮助,并祝您好运! :-p


0
投票

您的“公钥”实际上是一个证书(具体是X.509 v1或v3证书,具体取决于您的openssl配置),它包含一个公钥,但不同于公钥,并且是PEM格式即使您误导了它的名称.der-并且您的私钥已加密。

除了使用PKCS12的方法外,正如Roberto所建议的那样,并且通常是最简单的,因为它仅是一个要管理的文件,并且仍然是加密的,因此更加安全:

  • Java可以处理X.509证书,但是您使用CertificateFactory.getInstance("X.509")并给它一个InputStream而不是KeyFactoryX509EncodedKeySpecCertificateFactory

    can

    可以处理PEM或DER,与KeyFactory只能处理DER的方式不同,因此您不需要de-PEM(条形BEGIN / END / EOL和对base64进行解码)。
] >
  • 标准Java无法直接处理加密的PKCS8密钥。如果您可以添加第三方库,那么BouncyCastle的bcpkix

    can

    可以这样做;搜索使用PEMParser(不是PEMReader,这是较早的版本)和JceOpenSSLPKCS8DecryptorBuilder的十几个现有Q。否则,您可以将-nodes添加到req -newkey -x509命令中以生成未加密
  • 私钥文件,在对它进行去PEM后,该does可以在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。未加密文件的风险与上面相同。

    © www.soinside.com 2019 - 2024. All rights reserved.