Java 如何使用JCA读取BouncyCastle私钥PEM文件?

Java 如何使用JCA读取BouncyCastle私钥PEM文件?,java,openssl,bouncycastle,pem,jca,Java,Openssl,Bouncycastle,Pem,Jca,在我们的一个应用程序中,私钥使用BouncyCastle的PEMWriter存储。目前,我正在调查我们是否可以摆脱BouncyCastle依赖,因为Java7似乎拥有我们所需要的一切。唯一的问题是我无法读取作为PEM编码字符串存储在数据库中的私钥(证书/公钥可以) 如果我将PEM编码的私钥字符串从数据库保存到文件中,我可以运行OpenSSL将密钥转换为PKCS#8格式,如下所示: openssl pkcs8 -topk8 -inform PEM -outform DER \

在我们的一个应用程序中,私钥使用BouncyCastle的PEMWriter存储。目前,我正在调查我们是否可以摆脱BouncyCastle依赖,因为Java7似乎拥有我们所需要的一切。唯一的问题是我无法读取作为PEM编码字符串存储在数据库中的私钥(证书/公钥可以)

如果我将PEM编码的私钥字符串从数据库保存到文件中,我可以运行OpenSSL将密钥转换为PKCS#8格式,如下所示:

openssl pkcs8 -topk8 -inform PEM -outform DER \
              -in private_key.pem -out private_key.der -nocrypt
我可以使用以下Java/JCA代码位对结果输出进行base64编码,然后读取:

byte[] privateKeyBytes = 
           DatatypeConverter.parseBase64Binary(privateKeyDERcontents);
PrivateKey prKey = 
           KeyFactory.getInstance("RSA").
               generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
此私钥与按预期存储的公钥相匹配,即我可以从明文到密文再返回

我的问题是:我是否可以以某种方式直接读取原始的PEM编码

编辑

下面是使用BouncyCastle读取相关字符串的代码:

if (Security.getProvider("BC") == null) {
    Security.addProvider(new BouncyCastleProvider());
}
PEMReader pemReader = new PEMReader(new StringReader(privateKeyPEM));
KeyPair keyPair = (KeyPair) pemReader.readObject();
PrivateKey key = keyPair.getPrivate();


“privateKeyPEM”是数据库中PEM编码的字符串,否则此示例是自包含的。有趣的是,它已经使用JCA密钥对对象作为输出。换言之,我的原始问题是:我是否可以在不依赖PEMReader的情况下执行与上述代码等效的操作(以及其他许多BouncyCastle类)?

PEM文件中的密钥已经以PKCS#8格式存储,因此,如果它没有使用密码加密,您只需删除头文件(----BEGIN RSA PRIVATE Key)--Base64解码输入,并获取所需的字节。

PEM文件中的密钥已经以PKCS#8格式存储,因此如果未使用密码对其进行加密,您只需删除头文件(----BEGIN RSA PRIVATE Key-----),Base64解码输入,并获取所需的字节。

我很确定这是错误的。PEM文件可能包含PKCS#8编码密钥,但也可能包含其他二进制数据。例如X.509证书(通常用于公钥)和OpenSSL的默认值(某种专有格式)。您可以将openssl转换为从一个get到另一个get,同时将PEM作为外部编码——使用我给出的命令,将-inform和-outform都设置为PEM。当然,PEM只是二进制数据的文本编码。我说的是这种特殊情况。这里有Base64编码的PKCS#8私钥。需要使用openssl命令将其转换为PKCS#8。请参见,例如——我在该文档中的密钥格式似乎是“传统的”。@彼得贝克:你似乎没有抓住要点。您不想使用Bouncycastle。有人告诉你,你不必这么做。现在你又开始谈别的话题了。@GregS:我怎么会错过要点呢?我不想使用BC,但我仍然无法仅使用JDK读取数据库中的私钥。Nickolay声称钥匙应该是PKCS#8,但事实并非如此。它们的格式使得OpenSSL转换成为必需,直到我找到其他方法才能实现。我很确定这是不对的。PEM文件可能包含PKCS#8编码密钥,但也可能包含其他二进制数据。例如X.509证书(通常用于公钥)和OpenSSL的默认值(某种专有格式)。您可以将openssl转换为从一个get到另一个get,同时将PEM作为外部编码——使用我给出的命令,将-inform和-outform都设置为PEM。当然,PEM只是二进制数据的文本编码。我说的是这种特殊情况。这里有Base64编码的PKCS#8私钥。需要使用openssl命令将其转换为PKCS#8。请参见,例如——我在该文档中的密钥格式似乎是“传统的”。@彼得贝克:你似乎没有抓住要点。您不想使用Bouncycastle。有人告诉你,你不必这么做。现在你又开始谈别的话题了。@GregS:我怎么会错过要点呢?我不想使用BC,但我仍然无法仅使用JDK读取数据库中的私钥。Nickolay声称钥匙应该是PKCS#8,但事实并非如此。它们的格式使得OpenSSL转换成为必需,直到我找到其他方法才能进行转换。openssl命令生成DER输出,但java代码base64对此进行了解码。这行不通,因为它一开始不是base64编码的。@GregS:你是对的,我一定是把实验中的错误比特组合起来了。让我检查一下效果:我要么使用“-outform PEM”并剥离页眉/页脚(可能),要么对DER输出进行base64编码(不太可能)。我很快就会编辑这篇文章。@GregS:simply base64编码DER是有效的,所以我们假设是我做的。如果包装为64个字符,则与PEM相同。您的第一位代码与openssl命令不符。openssl命令生成DER输出,但java代码base64对此进行了解码。这行不通,因为它一开始不是base64编码的。@GregS:你是对的,我一定是把实验中的错误比特组合起来了。让我检查一下效果:我要么使用“-outform PEM”并剥离页眉/页脚(可能),要么对DER输出进行base64编码(不太可能)。我很快就会编辑这篇文章。@GregS:simply base64编码DER是有效的,所以我们假设是我做的。如果包装为64个字符,则无论如何与PEM相同。