如何将证书从PEM格式转换为JKS格式?

24

我需要将PEM格式的证书转换为Java密钥库。

在Windows服务器上使用它与Tomcat一起使用。

我有以下文件:

  • cert_request.csr

      -----BEGIN CERTIFICATE REQUEST-----
      ...
      -----END CERTIFICATE REQUEST-----
    
  • cert_public_key.pem

      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    
  • cert_private_key.pem

      -----BEGIN ENCRYPTED PRIVATE KEY-----
      ...
      -----END ENCRYPTED PRIVATE KEY-----
    
  • cert.txt

  •   contains an 16 digit key
    

我试图将pem文件(通过将两个已链接的文件合并)组合起来,并使用openssl将其转换为

  • .der文件,并将其导入新的密钥库中
  • 同样适用于.p12
  • 直接导入到密钥库

我还尝试更改

    -----BEGIN ENCRYPTED PRIVATE KEY-----
    ...
    -----END ENCRYPTED PRIVATE KEY-----

转化为

    -----BEGIN RSA PRIVATE KEY-----
    ...
    -----END RSA PRIVATE KEY-----

我尝试了上面的三种方法

我该怎么做才能得到一个可用的证书?

编辑:

我将cert_public_key.pem和cert_private_key.pem合并成cert_comb.pem

    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
    -----BEGIN ENCRYPTED PRIVATE KEY-----
    ...
    -----END ENCRYPTED PRIVATE KEY-----

这篇在jamielinux.com上的指南提供了许多关于如何生成密钥对、如何生成证书、如何生成CSR以及如何使用证书签署CSR的答案;之后,您可以使用keytool将它们合并,或者您可以使用具有GUI的Portecle。 https://jamielinux.com/docs/openssl-certificate-authority/introduction.html - EpicPandaForce
2个回答

47

您没有明确指出合并了哪些文件,但使用openssl将证书和私钥合并成PKCS#12应该可以正常工作:

cat cert_public_key.pem cert_private_key.pem >combined.pem
openssl pkcs12 -export -in combined.pem -out cert.p12

或者即时生成,但是(更新:)私钥必须首先出现:

cat cert_private_key.pem cert_public_key.pem | openssl pkcs12 -export -out cert.p12 

如果您的证书需要任何链证书 - 当您提交CSR并发放证书时,CA应该告诉您此信息 - 最简单的方法是现在也包含它(它们)。

然后(1) 一些 Java程序实际上可以直接使用pkcs12作为密钥库,但是(2)如果您需要或更喜欢JKS,请使用keytool:

keytool -importkeystore -srckeystore cert.p12 -srcstoretype pkcs12 -destkeystore cert.jks 

如果您在生成的JKS中关心别名(alias),最容易的方法是在转换后进行修复。

另外,仅更改加密PEM中的标签并不会解密它,将标签从通用PKCS#8更改为RSA也不会实际更改数据以匹配(尽管只有些许不同)。如果您确实想要一个带有解密私钥的单独PEM文件:

openssl pkey -in encryptedpk8 -out clearpk8.pem # 1.0.0 up
openssl pkcs8 -in encryptedpk8 -out clearpk8.pem # 1.0.0 up 
openssl pkcs8 -topk8 -nocrypt -in encryptedpk8 -out clearpk8.pem # below 1.0.0
openssl rsa -in encryptedpk8 -out clearrsa.pem

我将cert_public_key.pem和cert_private_key.pem合并为cert_comb.pem,并编辑了上面的帖子。 - Narf
我必须使用Windows,所以我没有使用cat复制它。我在文本编辑器(notepad ++)中手动复制了它。 - Narf
我尝试合并两个 .pem 文件并执行命令 "pkcs12 -export -out C:/path/cert.p12 -in C:/path/cert_comb.pem",但是出现错误:"无法写入'随机状态'". - Narf
是的,在Windows上使用openssl完成所请求的操作后,通常会出现该错误,因此在几乎所有情况下,您都可以忽略它。如果您想要修复,请参见https://dev59.com/Amcs5IYBdhLWcg3w433H https://dev59.com/2HVD5IYBdhLWcg3wE3bz - dave_thompson_085
1
@Arash:假设您指的是一个PEM格式的证书(认证不是标准术语)和私钥在同一个文件中,那么这已经在我的答案的第一部分中涵盖了。 (请注意,此问题的OP使用“cert_public_key”作为证书的名称。)(还请注意,与2014年不同,今天所有支持的Java版本都默认使用PKCS12密钥库。) - dave_thompson_085
显示剩余6条评论

1
第一个问题:您只有证书请求吗?没有实际的证书? 它需要被签名,您可以自行签名,也可以由外部方签名。
如果您拥有实际证书,则可以使用此证书来解析私钥文件和证书文件:
// parse the private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // might not be RSA
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(byteArray);
PrivateKey privateKey = keyFactory.generatePrivate(spec);

// parse cert
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate cert = factory.generateCertificate(certInputStream);

// add it to the keystore
store.setKeyEntry(alias, privateKey, password, new X509Certificate[] { cert });

更新

据我所知,命令行工具keytool不支持像签署csr这样的高级选项。即使是标准的Java也不支持此功能,您需要使用外部库,例如Bouncy Castle。这并不容易。例如:

JcaPKCS10CertificationRequest pkcs10 = new JcaPKCS10CertificationRequest(csrBytes);
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
        issuer,
        generateSerialId(),
        new Date(),
        until,
        subject,
        pkcs10.getPublicKey()
);

X509CertificateHolder holder = builder.build(getContentSigner(privateKey, type));
X509Certificate cert = getCertificate(holder);

...

ContentSigner getContentSigner(PrivateKey privateKey) {
    AsymmetricKeyParameter keyParameter = PrivateKeyFactory.createKey(privateKey.getEncoded());
    AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WITHRSA"); // or what you want
    AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
    return new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(keyParameter);
}

我有4个文件,一个cert_request.csr,cert_public_key.pem,cert_private_key.pem和cert.txt。 - Narf
cert.txt 只有 16 位数字,不确定其中包含什么,是一个 ID 吗?公钥在这里并不重要。CSR(证书签名请求)必须由某人签名才能生成证书。证书和私钥一起放入密钥库中。CSR 在签名后可以忽略。 - nablex
到目前为止我理解了,但是怎么做呢? 我正在寻找一个命令行表达式。 - Narf
我该如何运行这段代码?请帮帮我。我有一个包含证书和私钥的sslcertification.pem文件,我想将其转换为Java keystore格式。 - Arash
Q中的数据清楚地显示,“cert_public_key.pem”实际上是一个证书。虽然在这里不适用,但自2011年Java 7以来,keytool -gencert可以从CSR创建证书(这并不是通过签署CSR完成的,尽管许多人和网站错误地声称如此)。 - dave_thompson_085

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