首页 > 解决方案 > 是否可以使用具有不同密钥对的现有 CA 生成签名证书?

问题描述

正如我在这篇文章中解释的那样,我使用现有 CA 创建了一个签名证书:Bouncy Castle: Signed Certificate with an existing CA

但是,我生成的证书与 CA 证书具有相同的公钥和私钥。

是否可以生成具有另一个密钥对的证书?

我已尝试以下帖子中的示例代码,但我的 pdf 签名无效:使用 Bouncy Castle Java 生成 X509 证书

我将不胜感激任何可以帮助我的评论或信息。

提前致谢。

标签: javabouncycastlesignaturecacsr

解决方案


仅当证书是自签名证书时,公钥证书 (PKC) 才会与颁发者具有相同的密钥对(公钥) 。CA 始终可以为另一个密钥对颁发证书,在这种情况下,新证书将具有新密钥对的公钥,并将由 CA 的私钥签名。这个新证书的主题又可以成为一个 CA(通过 BasicConstraint 扩展和 KeyUsage 扩展),在这种情况下,新的密钥对可以用于颁发其他证书,从而创建证书路径或链。请参阅以下代码片段。

public static X509Certificate getCertificte(X500Name subject,
                                          PublicKey subjectPublicKey,
                                          boolean isSubjectCA,
                                          X509Certificate caCertificate,
                                          PrivateKey caPrivateKey,
                                          String signingAlgorithm,
                                          Date validFrom,
                                          Date validTill) throws CertificateEncodingException {

BigInteger sn = new BigInteger(64, random);

X500Name issuerName = new X500Name(caCertificate.getSubjectDN().getName());
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(subjectPublicKey.getEncoded());

X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(issuerName,
                                                                    sn,
                                                                    validFrom,
                                                                    validTill,
                                                                    subject,
                                                                    subjectPublicKeyInfo);

JcaX509ExtensionUtils extensionUtil;
try {
  extensionUtil = new JcaX509ExtensionUtils();
} catch (NoSuchAlgorithmException e) {
  throw new RuntimeException("No provider found for SHA1 message-digest");
}

// Add extensions
try {
  AuthorityKeyIdentifier authorityKeyIdentifier = extensionUtil.createAuthorityKeyIdentifier(caCertificate);
  certBuilder.addExtension(Extension.authorityKeyIdentifier, false, authorityKeyIdentifier);

  SubjectKeyIdentifier subjectKeyIdentifier = extensionUtil.createSubjectKeyIdentifier(subjectPublicKey);
  certBuilder.addExtension(Extension.subjectKeyIdentifier, false, subjectKeyIdentifier);

  BasicConstraints basicConstraints = new BasicConstraints(isSubjectCA);
  certBuilder.addExtension(Extension.basicConstraints, true, basicConstraints);
} catch (CertIOException e) {
  throw new RuntimeException("Could not add one or more extension(s)");
}

ContentSigner contentSigner;
try {
  contentSigner = new JcaContentSignerBuilder(signingAlgorithm).build(caPrivateKey);
} catch (OperatorCreationException e) {
  throw new RuntimeException("Could not generate certificate signer", e);
}

try {
   return new JcaX509CertificateConverter().getCertificate(certBuilder.build(contentSigner));
 } catch (CertificateException e) {
   throw new RuntimeException("could not generate certificate", e);
 }
}

请注意参数:
subjectPublicKey:与将为其颁发新证书的新密钥对对应的公钥。

caCertificate:与当前 CA 的密钥对对应的 CA 证书。

caPrivateKey : CA 的私钥(对应上述 caCertificate 的私钥)。这将用于签署新证书。

isSubjectCA:一个布尔值,指示新证书持有者(主题)是否将充当 CA。

为简洁起见,我省略了 keyUsage 扩展,它应该用于指示应该使用与新证书对应的公钥的所有用途。


推荐阅读