使用bouncy castle API在java中建立版本3,X.509證書層次結構

在本文中,我將討論使用 bouncy castle API 在 java 程序中建立 SSL 證書。 Bouncy castle 是一種輕量級加密 API。它是 Java Cryptography Extension(JCE)和 Java Cryptography Architecture(JCA)的實現。java

我將建立很是基本的證書,其中只包含必要的屬性。您能夠瀏覽 API 以獲取可應用於證書的更多操做和屬性git

請在代碼中導入如下依賴項。算法

<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
     <dependency>
       <groupId>org.bouncycastle</groupId>
       <artifactId>bcpkix-jdk15on</artifactId>
       <version>1.55</version>
     </dependency>
     <!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
     <dependency>
       <groupId>joda-time</groupId>
       <artifactId>joda-time</artifactId>
       <version>2.9.4</version>
     </dependency>
複製代碼

我在代碼中執行如下步驟: 步驟: 1)建立自簽名根證書。 2)建立在步驟 1 中建立的根證書籤名的中間證書. 3)建立在步驟 2 中建立的中間證書籤名的最終用戶證書。瀏覽器

代碼:dom

import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x509.BasicConstraints;
 import org.bouncycastle.asn1.x509.Extension;
 import org.bouncycastle.asn1.x509.KeyUsage;
 import org.bouncycastle.cert.X509v3CertificateBuilder;
 import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
 import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import org.joda.time.DateTime;

 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.security.*;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.Random;


 public class App {

   public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, OperatorCreationException, InvalidKeyException, NoSuchProviderException, SignatureException, UnrecoverableKeyException {
     Security.addProvider(new BouncyCastleProvider());

     // Create self signed Root CA certificate
     KeyPair rootCAKeyPair = generateKeyPair();
     X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
         new X500Name("CN=rootCA"), // issuer authority
         BigInteger.valueOf(new Random().nextInt()), //serial number of certificate
         DateTime.now().toDate(), // start of validity
         new DateTime(2025, 12, 31, 0, 0, 0, 0).toDate(), //end of certificate validity
         new X500Name("CN=rootCA"), // subject name of certificate
         rootCAKeyPair.getPublic()); // public key of certificate
     // key usage restrictions
     builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign));
     builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
     X509Certificate rootCA = new JcaX509CertificateConverter().getCertificate(builder
         .build(new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").
             build(rootCAKeyPair.getPrivate()))); // private key of signing authority , here it is self signed
     saveToFile(rootCA, "D:\\rootCA.cer");


     //create Intermediate CA cert signed by Root CA
     KeyPair intermedCAKeyPair = generateKeyPair();
     builder = new JcaX509v3CertificateBuilder(
         rootCA, // here rootCA is issuer authority
         BigInteger.valueOf(new Random().nextInt()), DateTime.now().toDate(),
         new DateTime(2025, 12, 31, 0, 0, 0, 0).toDate(),
         new X500Name("CN=IntermedCA"), intermedCAKeyPair.getPublic());
     builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign));
     builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
     X509Certificate intermedCA = new JcaX509CertificateConverter().getCertificate(builder
         .build(new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").
             build(rootCAKeyPair.getPrivate())));// private key of signing authority , here it is signed by rootCA
     saveToFile(intermedCA, "D:\\intermedCA.cer");

     //create end user cert signed by Intermediate CA
     KeyPair endUserCertKeyPair = generateKeyPair();
     builder = new JcaX509v3CertificateBuilder(
         intermedCA, //here intermedCA is issuer authority
         BigInteger.valueOf(new Random().nextInt()), DateTime.now().toDate(),
         new DateTime(2025, 12, 31, 0, 0, 0, 0).toDate(),
         new X500Name("CN=endUserCert"), endUserCertKeyPair.getPublic());
     builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature));
     builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(false));
     X509Certificate endUserCert = new JcaX509CertificateConverter().getCertificate(builder
         .build(new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").
             build(intermedCAKeyPair.getPrivate())));// private key of signing authority , here it is signed by intermedCA
     saveToFile(endUserCert, "D:\\endUserCert.cer");
   }

   private static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
     KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
     kpGen.initialize(2048, new SecureRandom());
     return kpGen.generateKeyPair();
   }

   private static void saveToFile(X509Certificate certificate, String filePath) throws IOException, CertificateEncodingException {
     FileOutputStream fileOutputStream = new FileOutputStream(filePath);
     fileOutputStream.write(certificate.getEncoded());
     fileOutputStream.flush();
     fileOutputStream.close();
   }

 }
複製代碼

在這裏你能夠看到,對於 rootCA,我使用本身的私鑰來簽署證書。對於 intermedCA,我使用 rootCA 私鑰進行簽名。對於最終用戶證書,我使用 IntermedCA 私鑰進行簽名。 在現實生活中,您還能夠看到與此相似的證書鏈。從瀏覽器打開任何 HTTPS 鏈接證書,並觀察證書鏈和每一個證書的屬性。ide

「SHA256withRSA」是我用它來簽名證書的簽名算法。 在 keyUsage 中,「keyCertSign」僅限制證書使用以簽署其餘證書。雖然 SSL 客戶端須要「digitalSignature」使用,但咱們的 Web 瀏覽器使用該證書進行實體身份驗證和數據源身份驗證的完整性。工具

BasicConstraints 中的「true」標誌將證書標記爲能夠簽署其餘證書的 CA 證書。「false」標誌將證書標記爲證書鏈的最終實體。ui

做爲此程序的出現,您將在指定的文件路徑中擁有 3 個證書。加密

如今首先打開 rootCA:spa

您能夠看到證書不可信的消息。所以,咱們將此證書添加到受信任的根證書存儲區中

1)單擊「安裝證書」按鈕。 2)選擇「本地計算機」,單擊下一步 3)選擇「將全部證書放在如下存儲中」的第二個選項 4)瀏覽並選擇「受信任的根證書頒發機構」 5)單擊「下一步」,而後單擊「完成」。 6)導入成功。

對於「Intermed CA」證書執行相同的操做,僅在步驟 4 中進行更改:瀏覽並選擇「中間證書頒發機構」。

如今關閉證書並從新打開它。 讓咱們如今檢查每一個證書:

  1. RootCA

  1. 中間 CA

  1. 最終用戶證書

還有其餘方法能夠建立證書和證書鏈。例如:java「keytool」命令或使用「keystore explorer」之類的工具.... 但不少時候你必須從程序中進行證書操做。 因此這在當時會很是有用。

在下一篇文章中,我將更多地介紹證書的主題以及您可使用 java 程序中的 bouncy castle 執行的操做。

相關文章
相關標籤/搜索