在本教程中,我们学习了如何使用 Bouncy Castle 库签署 CSR。我们生成了密钥对,创建了 CSR,生成了 CA 密钥对,并使用 CA 证书签署了 CSR。我们还编写了一个测试来验证签名过程。
签署证书签名请求 (CSR) 是密码学中的常见操作。在本教程中,我们将学习如何使用 Bouncy Castle 库签署 CSR。
签署 CSR
签署 CSR 是证书颁发机构 (CA) 验证 CSR 中的信息并颁发证书的过程。CA使用其私钥签署证书。签署的证书随后可以在客户端和服务器之间建立安全连接。
要使用 Bouncy Castle 签署 CSR,我们需要执行几个基本步骤:
- 生成受信任实体CA证书和私钥。
- 生成证书签名请求 (CSR)。
- 使用 CA 证书和私钥签署 CSR。
设置
我们需要将 Bouncy Castle 库添加到我们的项目中,以便我们可以使用它来签署 CSR。让我们将其Maven 依赖项添加到我们的pom.xml文件中:
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk18on</artifactId> <version>1.76</version> </dependency>
|
接下来,我们需要创建一个SecurityProvider类来注册 Bouncy Castle 提供程序:static { Security.addProvider(new BouncyCastleProvider()); }
|
使用 Bouncy Castle 签署 CSR
使用 Bouncy Castle 签署 CSR 涉及几个步骤。让我们详细了解每个步骤。
1. 生成受信任实体 CA 证书和私钥
CA 是向客户端颁发证书的受信任实体。我们必须生成 CA 证书和私钥来签署 CSR。让我们从生成密钥对开始:
public static KeyPair generateRSAKeyPair() { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); return keyPairGenerator.generateKeyPair(); }
|
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); }
|
3. 签署证书签名请求
接下来,我们必须创建一个证书生成器,使用 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用于指定公钥信息。
接下来,我们创建证书生成器。它设置证书的颁发者、序列号、有效期、主题和公钥。
然后,我们使用签名和摘要算法以及 CA 的私钥创建ContentSigner,用于签署证书。
最后,该方法构建证书,将其转换为 X509Certificate ,并返回它。
测试
我们来编写一个测试来验证签名过程:
@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 公钥验证签名的证书。