使用 Bouncy Castle 签署 CSR
1、概览
签署(也叫做签发)证书签名请求(CSR)是密码学中的一项常见操作。本文将带你了解如何使用 Bouncy Castle 签署 CSR。
2、签署 CSR
签署 CSR 是证书颁发机构(CA)验证 CSR 中的信息并颁发证书的过程。CA 使用其私钥签署证书。签名后的证书可在客户端和服务器之间建立安全连接。
要使用 Bouncy Castle 签署 CSR,需要执行几个基本步骤:
- 生成可信实体 CA 证书和私钥。
- 生成证书签名请求(CSR)。
- 使用 CA 证书和私钥签署 CSR。
3、设置
首先,需要在 pom.xml
中添加 Bouncy Castle 依赖:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.76</version>
</dependency>
接下来,需要创建一个 SecurityProvider
类来注册 Bouncy Castle Provider:
static {
Security.addProvider(new BouncyCastleProvider());
}
4、使用 Bouncy Castle 签署 CSR
使用 Bouncy Castle 签署 CSR 需要几个步骤。
4.1、生成可信实体 CA 证书和私钥
CA 是向客户签发证书的可信实体。我们必须生成 CA 证书和私钥来签署 CSR。
先生成一个密钥对:
public static KeyPair generateRSAKeyPair() {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
return keyPairGenerator.generateKeyPair();
}
4.2、生成证书签署请求
根据密钥对创建证书签名请求(CSR):
public static PKCS10CertificationRequest generateCSR(KeyPair pair) {
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
new X500Principal("CN=Requested Test Certificate"), pair.getPublic());
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");
ContentSigner signer = csBuilder.build(pair.getPrivate());
return p10Builder.build(signer);
}
4.3、签署证书签名请求(CSR)
接下来,创建一个证书生成器,使用 CA 证书和私钥签署 CSR。
签署 CSR:
public X509Certificate sign(PKCS10CertificationRequest inputCSR, PrivateKey caPrivate, KeyPair pair) {
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
AsymmetricKeyParameter foo = PrivateKeyFactory.createKey(caPrivate.getEncoded());
SubjectPublicKeyInfo keyInfo = SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
X509v3CertificateBuilder myCertificateGenerator = new X509v3CertificateBuilder(
new X500Name("CN=issuer"),
new BigInteger("1"),
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis() + 30L * 365 * 24 * 60 * 60 * 1000),
inputCSR.getSubject(),
keyInfo);
ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(foo);
X509CertificateHolder holder = myCertificateGenerator.build(sigGen);
Certificate eeX509CertificateStructure = holder.toASN1Structure();
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
InputStream is1 = new ByteArrayInputStream(eeX509CertificateStructure.getEncoded());
X509Certificate theCert = (X509Certificate) cf.generateCertificate(is1);
is1.close();
return theCert;
}
该方法首先要确定用于签署证书的签名和摘要算法。我们使用 DefaultSignatureAlgorithmIdentifierFinder
和 DefaultDigestAlgorithmIdentifierFinder
类查找这些算法。
AsymmetricKeyParameter
用于从编码后的字节数组中创建 CA 的私钥。
我们使用 PrivateKeyFactory
类从编码后的字节数组中创建私钥。SubjectPublicKeyInfo
用于指定公钥信息。
接下来,创建证书生成器。它为证书设置签发人(issuer)、序列号(serial number)、有效期(validity period)、主题(subject)和公钥(public key)。
然后,使用签名和摘要算法以及 CA 的私钥创建 ContentSigner
,用于签署证书。
最后,该方法会生成证书,并将其转换为 X509Certificate
后返回。
5、测试
编写一个测试来验证签名过程:
@Test
public void givenCSR_whenSignWithBC_thenSuccess() {
SignCSRBouncyCastle signCSRBouncyCastle = new SignCSRBouncyCastle();
KeyPair pair = SignCSRBouncyCastle.generateRSAKeyPair();
PKCS10CertificationRequest csr = SignCSRBouncyCastle.generateCSR(pair);
KeyPair caPair = SignCSRBouncyCastle.generateRSAKeyPair();
X509Certificate signedCert = signCSRBouncyCastle.signCSR(csr, caPair.getPrivate(), pair);
assertThat(signedCert).isNotNull();
assertThat(signedCert.getSubjectDN().getName()).isEqualTo("CN=Requested Test Certificate");
assertDoesNotThrow(() -> signedCert.verify(caPair.getPublic()));
}
如上,我们生成一对密钥并创建 CSR。然后,生成 CA 密钥对,并使用 CA 私钥签署 CSR。最后,使用 CA 公钥验证已签署的证书。
6、总结
本文介绍了如何使用 Bouncy Castle 库签署 CSR。
我们首先生成了密钥对,创建了 CSR,然后生成了 CA 密钥对,并使用 CA 证书签署了 CSR。最后还编写了一个测试来验证签名过程。
Ref:https://www.baeldung.com/java-bouncy-castle-sign-csr