针对Java的RSA密钥转换 - 需要澄清吗?

时间:2013-09-17 17:42:02

标签: java encryption openssl rsa public-key-encryption

我读了一些关于将密钥从PEM转换为DER的已知问题,因此Java可以读取它们,然后我跑了this article。接下来,这可以正常工作 - 生成带有openssl的RSA密钥对,密钥加载正常,用公钥加密的内容用私钥成功解码。

现在,这是不清楚的部分 不久前,我使用Easy-RSA实用程序生成PKI,同时设置OpenVPN服务器。在这里,创建了一个自签名证书。输出文件包括:

  

server.csr ------ //证书申请
  server.key ------ //私钥
  server.crt ------- //自签名证书/公钥/这是什么..?

仅供参考,easy-RSA is documented(在页面底部是解释的脚本,我们可以看到过程中实际使用的openssl命令)。

所以,我在这些文件上尝试了上述逻辑,使用server.key作为我的私钥文件,server.crt作为我的公钥文件,先前已将转换为Java - 可读的DER格式:

  

openssl pkcs8 -topk8 -inform PEM -outform DER -in server.key -out server_private_key.der -nocrypt   openssl x509 -inform PEM -outform DER -text -in server.crt -out server.der

私钥,不是那么奇怪,工作正常,即它已成功加载到Java中 公钥(再次,可能不是那么奇怪)不会加载,但我不知道原因,因为我并不熟悉所有这些东西。我的猜测是,这与签署的证书有关,我想知道在这些情况下如何处理这个问题。我得到以下异常:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException:IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
  at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)
  at java.security.KeyFactory.generatePublic(KeyFactory.java:304)
  at aes.utils.KeyReaderUtil.getPublicKeyFromFile(KeyReaderUtil.java:57)
  at aes.utils.Main.main(Main.java:69)
Caused by: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data
isn't an object ID (tag = -96)
  at sun.security.x509.X509Key.decode(X509Key.java:380)
  at sun.security.x509.X509Key.decode(X509Key.java:386)
  at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:66)
  at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:281)
  at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:184)
  ... 3 more

此外,当我从现有的server.key私钥文件中“导出”公钥时,如下所示(如上文所述):

  

openssl rsa -in server.key -pubout -outform DER -out server_public_key.der

一切正常。

所以,我的问题是:什么是正确的方法,为什么server.crt不会作为公钥加载?

1 个答案:

答案 0 :(得分:8)

您链接的文章中的Java代码需要一个公钥文件,而不是X509证书,这是您在server.crt中所拥有的。

X509证书包含公钥以及通过签名绑定到该密钥的身份信息。

从Java的X509Certificate documentation,您可以找到以下代码:

 InputStream inStream = null;
 try {
     inStream = new FileInputStream("fileName-of-cert");
     CertificateFactory cf = CertificateFactory.getInstance("X.509");
     X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
 } finally {
     if (inStream != null) {
         inStream.close();
     }
 }

一旦你拥有X509证书对象,就可以轻松获得这样的PublicKey:

PublicKey myPubKey = cert.getPublicKey();