将PKCS#1格式的私钥转换为PKCS#8格式的私钥,使用Java

5
我有一个PKCS#1格式的私钥(由opendkim-genkey生成),如下所示:
-----BEGIN RSA PRIVATE KEY-----

Base64 encoded data

-----END RSA PRIVATE KEY-----

现在我需要在Java中使用它来生成java.security.PrivateKey。

但是Java只支持PKCS#8格式的私钥。

我知道有一种方法可以通过Java(使用Bouncycastle)从PKCS#8转换为PKCS#1,但是否有任何方式可以通过Java将PKCS#1转换为PKCS#8?


您可以使用openssl命令执行此操作,例如:openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in pkcs1.key -out pkcs8.key。请参考这里 - Ben
谢谢,我知道可以使用openssl命令行来完成。 但是我想问的是,我们是否可以通过Java来实现它。 - Thanh Vũ
为什么要重新编写 Java 代码,当一个已经存在的实用程序已经可以正确完成这个过程,而且您只需要在重新键入时每隔几年执行一次? - user207421
你需要将其转换还是仅使用它?这两者并不相同。要在Java中使用BouncyCastle使用PKCS1 RSAPrivateKey(又名OpenSSL传统明文),请参见https://dev59.com/blgQ5IYBdhLWcg3w-o1w。 - dave_thompson_085
2个回答

2
将一个PKCS#1编码的RSA私钥转换为可由普通Java使用的PKCS#8是可能的,可以使用Bouncy Castle的bcprov库。
由于PKCS#1和PKCS#8之间的区别仅仅是前导PrivateKeyAlgorithmIdentifier,因此我们可以补充该标识以获取PKCS#8:
byte[] pkcs1Encoded = ...;

AlgorithmIdentifier algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(algId, ASN1Sequence.getInstance(pkcs1Encoded));

byte[] pkcs8Encoded = privateKeyInfo.getEncoded();

这可以被普通的 Java 所使用:
java.security.spec.KeySpec spec = new java.security.spec.PKCS8EncodedKeySpec(pkcs8Encoded);
java.security.KeyFactory.getInstance("RSA").generatePrivate(spec);

然而,如果您已经在使用Bouncy Castle,您可以使用它们的提供程序,不需要显式地将PKCS#1转换为PKCS#8,因为它们的KeyFactorySpi可以使用一个包含PKCS#1的PKCS8EncodedKeySpec

e.g.:

java.security.spec.KeySpec spec = new java.security.spec.PKCS8EncodedKeySpec(pkcs1Encoded);
java.security.KeyFactory.getInstance("RSA", new BouncyCastleProvider()).generatePrivate(spec);

Bouncy Castle提供者也可以全局注册:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

...

java.security.spec.KeySpec spec = new java.security.spec.PKCS8EncodedKeySpec(pkcs1Encoded);
java.security.KeyFactory.getInstance("RSA").generatePrivate(spec);

0

免责声明:本解决方案并非由我亲自编写,而是由github上的marcoscottwright编写。在此处查找原始代码


如果您有一个PrivateKey k对象,您可以使用BouncyCastle来实现此操作。

try (ASN1InputStream asn1InputStream = new ASN1InputStream(k.getEncoded()))
{
    DERObject rsaPrivateKey = asn1InputStream.readObject();
    return new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption), rsaPrivateKey).getDEREncoded();
}

1
这只是一半的答案。OP没有PrivateKey对象,他有一个以PKCS#1格式存储在文件中的RSA私钥。 - President James K. Polk

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