从 PKCS8 编码数据创建任何 PrivateKey 实例(RSA 或 DSA 或 EC)

Create any PrivateKey instance (RSA or DSA or EC) from PKCS8 encoded data

我有一个代表私钥的未加密 PKCS8 编码文件。它可以是这些私钥类型中的任何一种 - RSA、DSA 或 EC。我在 ASN1 解码器 (https://lapo.it/asn1js/) 中查看了这些文件,我可以在数据中看到类型(RSA、DSA 或 EC)。

有没有一种方法可以将 PKC8 私钥数据读取到正确的私钥 Java 对象中,而无需像这样在代码中指定密钥类型 -

PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pkcs8key);
KeyFactory factory = KeyFactory.getInstance("RSA"); // Avoid "RSA" here?
PrivateKey privateKey = factory.generatePrivate(spec);

有没有办法避免在KeyFactory.getInstance("RSA")中指定算法?这不应该根据 PKCS8EncodedKeySpec 确定,因为它在 PKCS8 数据中可用吗?

示例未加密的 PKCS8 数据及其显示密钥类型的 ASN1 解码 -

动态搜索广告 - link

EC - link

RSA - link

这可以在 BouncyCastle API 的帮助下实现 -

/** Read a PKCS#8 format private key. */
private static PrivateKey readPrivateKey(InputStream input)
throws IOException, GeneralSecurityException {
    try {
        byte[] buffer = new byte[4096];
        int size = input.read(buffer);
        byte[] bytes = Arrays.copyOf(buffer, size);
        /* Check to see if this is in an EncryptedPrivateKeyInfo structure. */
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        /*
         * Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
         * OID and use that to construct a KeyFactory.
         */
        ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()));
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
        String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
        return KeyFactory.getInstance(algOid).generatePrivate(spec);
    } finally {
        input.close();
    }
}