Java BouncyCastle API 創建證書撤銷列表 CRL 和驗證證書有效性

創建 CRL 需要用到有 CRL 權限的 CA 機構私鑰和證書:

        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		// 準備好創建 CRL 所需的私鑰和證書
        PrivateKey caPrivateKey = ......
        X509Certificate caCertificate = ......

        X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(
                new X500Name(caCertificate.getSubjectDN().getName()),
                new Date()
        );
        crlBuilder.setNextUpdate(new Date(System.currentTimeMillis() + 86400 * 1000)); // 1 天有效期

		crlBuilder.addCRLEntry(111/*被撤銷證書序列號*/, new Date() /*被撤銷時間*/, 1 /*被撤銷原因*/);

        JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA256WithRSA");
        contentSignerBuilder.setProvider("BC");
        X509CRLHolder crlHolder = crlBuilder.build(contentSignerBuilder.build(caPrivateKey));
        JcaX509CRLConverter converter = new JcaX509CRLConverter();
        converter.setProvider("BC");
        X509CRL crl = converter.getCRL(crlHolder);

根證書創建方法可以看:根據 CSR 創建證書

撤銷證書時需要指定撤銷原因,有以下幾種:

原因 說明
unspecified 未指定
keyCompromise 私鑰泄漏
cACompromise CA 私鑰可能泄漏
affiliationChanged 組織變化,隸屬關係變更
superseded 被取代
cessationOfOperation CA 停用
certificateHold 臨時吊銷
removeFromCRL 使用 certificateHold 吊銷的證書,可以用 removeFromCRL 取消吊銷
privilegeWithdrawn 因證書某權限被撤銷而吊銷
aACompromise indicates that it is known or suspected that aspects of the AA validated in the attribute certificate have been compromised

如果驗證一個證書是否在 CRL 撤銷列表裏呢?

		// 讀取 CRL 對象
		X509CRL x509CRL = ......
		// 讀取簽發 CRL 的公鑰,一般簽發 CRL 的公鑰和簽發證書的公鑰是相同的
        PublicKey publicKey = ......
        // 驗證 CRL 合法性
        x509CRL.verify(publicKey);
        // 讀取待驗證的證書
        X509Certificate certificate = ......
        // 驗證該證書是否被撤銷
        boolean isRevoked = x509CRL.isRevoked(certificate);

isRevoked 方法具體做了哪些事呢?可以看下 X509CRLImpl 裏的實現:

  1. 判斷證書類型是否是 X.509
  2. 判斷證書序列號是否在 CRL 裏
  3. 判斷證書籤發者和 CRL 簽發者是否是同一個
public boolean isRevoked(Certificate var1) {
        if (!var1.getType().equals("X.509")) {
            throw new IllegalArgumentException("X.509 CRL used with non X.509 Cert");
        } else {
            Enumeration var2 = this.c.getRevokedCertificateEnumeration();
            X500Name var3 = this.c.getIssuer();
            if (var2.hasMoreElements()) {
                BigInteger var4 = ((X509Certificate)var1).getSerialNumber();

                while(var2.hasMoreElements()) {
                    CRLEntry var5 = CRLEntry.getInstance(var2.nextElement());
                    if (this.isIndirect && var5.hasExtensions()) {
                        Extension var6 = var5.getExtensions().getExtension(Extension.certificateIssuer);
                        if (var6 != null) {
                            var3 = X500Name.getInstance(GeneralNames.getInstance(var6.getParsedValue()).getNames()[0].getName());
                        }
                    }

                    if (var5.getUserCertificate().hasValue(var4)) {
                        X500Name var9;
                        if (var1 instanceof X509Certificate) {
                            var9 = X500Name.getInstance(((X509Certificate)var1).getIssuerX500Principal().getEncoded());
                        } else {
                            try {
                                var9 = org.bouncycastle.asn1.x509.Certificate.getInstance(var1.getEncoded()).getIssuer();
                            } catch (CertificateEncodingException var8) {
                                throw new IllegalArgumentException("Cannot process certificate: " + var8.getMessage());
                            }
                        }

                        if (!var3.equals(var9)) {
                            return false;
                        }

                        return true;
                    }
                }
            }
            return false;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章