从PKCS12创建PrivateKey对象

4

我使用以下命令从PKCS12文件中创建了私钥:

openssl pkcs12 -in test.p12 -nocerts -out privateKey.pem

现在我该如何从privateKey.pem文件创建PrivateKey对象呢?

我尝试使用以下代码将PKCS12文件本身转换:

 KeyStore pfx = KeyStore.getInstance("pkcs12");
 pfx.load(new FileInputStream(P12), "123456".toCharArray());
 final Enumeration<String> aliases = pfx.aliases(); //this is empty

pfx.aliases() - 这个函数是空的,我使用keytool验证了它确实是空的,没有任何条目。

keytool -v -list -storetype pkcs12 -keystore test.p12

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 0 entries

我的问题是如何使用以下代码创建私钥:
 public static RSAPrivateKey getPrivateKey(File privateKeyFile) throws IOException {
        byte[] keyBytes = new byte[(int) privateKeyFile.length()];
        FileInputStream fis = new FileInputStream(privateKeyFile);
        fis.read(keyBytes);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);// it works only with PKCS8
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(spec);
        return privKey;
    }

这段代码的问题在于它只适用于PKCS8,而我需要一些类似于PKCS12的东西。

你尝试过在PKCS#12中存储(自签名)证书吗? P12密钥库在Java上有一定的限制。 Java通常只识别私钥/证书条目。 Java 8 可能会给您更好的结果,它有一个特定的项目来提供更多的PKCS#12功能。 - Maarten Bodewes
我该如何将证书存储在PKCS12文件中?我收到了一个证书文件和一个p12文件。我使用那个.cer文件获取公钥。 - user2662294
3个回答

3
我知道的唯一方法有点底层,但它有效:
public PrivateKey getPrivateKey(File file) throws IOException, GeneralSecurityException {
    try (FileInputStream fileStream = new FileInputStream(file);
         DataInputStream dataStream = new DataInputStream(fileStream)) {
        byte[] keyBytes = new byte[(int) file.length()];
        dataStream.readFully(keyBytes);
        String temp = new String(keyBytes);
        String header = temp.replace("-----BEGIN PRIVATE KEY-----\n", "");
        header = header.replace("-----END PRIVATE KEY-----", "");
        byte[] decoded = new Base64().decode(header);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }
}

这段代码假设所需的密钥是RSA密钥。


嗨,谢谢!但是它没有起作用java.security.InvalidKeyException: IOException : DER input, Integer tag error。原因是我们试图使用PKCS8,而实际上应该使用PKCS12。如果这段代码能够正常工作,那么我之前使用的代码也将不会出现任何问题。 - user2662294
你是想将 .p12 文件输入进去吗?这段代码是针对 .pem 写的,正如问题所述,你需要从 .pem 创建密钥。 - Jk1
不,我有一个privateKey.pem文件,是由openssl pkcs12 -in test.p12 -nocerts -out privateKey.pem命令生成的。该文件具有_BEGIN PRIVATE KEY_和_END PRIVATE KEY_字符串标记。我只是移除了这个标记并使用了纯私钥字符串。 - user2662294
如果文件格式是.pem,那么它不是PKCS12格式。PKCS12格式的表示应该是.pfx或.p12格式。因此,我敢说这里的根本原因有些不同。你能否分享有问题的.p12或.pem文件让我做一些实验吗? - Jk1
我找到了问题所在。原因是我收到的p12文件无效。非常感谢!!! - user2662294
@Jk1 PEM格式也被称为ASCII编码。它由头部和尾部组成,解释了所编码的内容,并包含一个Base64编码的编码数据表示。这很可能是PKCS#12密钥容器。在Java中,您需要首先对PEM容器进行解码,才能将其用作PKCS#12密钥存储。 - Maarten Bodewes

0
你可以尝试使用KeyStore Explorer(https://keystore-explorer.org/),我们使用它来代替Java Keytool(因为我觉得后者很难用)。

-1

也许这会对某些人有所帮助。

以下是如何从您的pkcs12证书文件生成私钥的方法。

public PrivateKey getPrivateKey(String pathToPKCS12File) {
    try {
        InputStream stream = new FileInputStream(new File(pathToPKCS12File));
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(stream, "123456".toCharArray());
        return (PrivateKey) ks.getKey(
            ks.aliases.nextElement(),
            "123456".toCharArray()
        );
    } catch (Exception e) {
        //error
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接