使用 Bouncy Castle 簽署 CSR
1. 概述
簽署憑證簽署要求 (CSR) 是密碼學中的常見操作。在本教程中,我們將學習如何使用 Bouncy Castle 庫簽署 CSR。
2. 簽署 CSR
簽署 CSR 是憑證授權單位 (CA) 驗證 CSR 中的資訊並頒發憑證的過程。 CA 使用其私鑰對憑證進行簽署。然後,簽署的憑證可以在客戶端和伺服器之間建立安全連線。
要使用 Bouncy Castle 簽署 CSR,我們需要執行一些基本步驟:
- 產生可信任實體 CA 憑證和私鑰。
- 產生憑證簽署請求 (CSR)。
- 使用 CA 憑證和私鑰簽署 CSR。
3. 設定
我們需要將 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());
}
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.簽署憑證簽署請求
接下來,我們必須建立一個憑證產生器來使用 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
並傳回它。
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 公鑰驗證簽署的憑證。
六、結論
在本教程中,我們學習如何使用 Bouncy Castle 庫簽署 CSR。我們產生了金鑰對,創建了 CSR,產生了 CA 金鑰對,並使用 CA 憑證簽署了 CSR。我們也編寫了一個測試來驗證簽名過程。
與往常一樣,這些範例的完整實作可以在 GitHub 上找到。