2013-05-07 67 views
1

我已成功使用Bouncy Castle的X509v3CertificateBuilder Java類創建具有標準V3擴展的X509證書。我正在嘗試使用自定義擴展名創建證書。使用Bouncy Castle在Java中創建自定義X509 v3擴展

我可以使用addExtension(...)方法創建自定義擴展,但是,證書中的結果值不是我想要的。例如,我想要在自定義OID 1.2.3.4下的證書中列出的這些確切的八位字節:「00 00 00 00 FF FF FF FF」。我試過的所有東西都包含在ASN1編碼中的八位字節字符串,並最終以「04 08 00 00 00 00 FF FF FF FF」結尾。

基本上,我想在Java中創建的證書與自定義擴展,看起來相同,當使用OpenSSL使用過這種配置的擴展文件創建的證書會怎樣看:

1.2.3.4=DER:00:00:00:00:FF:FF:FF:FF 

這是可以使用X509v3CertificateBuilder類以乾淨的方式進行操作嗎?

下面是創建「不正確」值的代碼片段。

// Raw value to place in cert for OID 1.2.3.4. 
    byte[] bytearray = {0, 0, 0, 0, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; 

    ASN1ObjectIdentifier asn1oid = new ASN1ObjectIdentifier("1.2.3.4"); 

    Extension ext = new Extension(asn1oid, false, bytearray); 

    X509v3CertificateBuilder certBldr = 
    new JcaX509v3CertificateBuilder(
     caCert, 
     serial, 
     startDate, 
     endDate, 
     dn, 
     pubKey) 
    .addExtension(
     new ASN1ObjectIdentifier("2.5.29.19"), 
     false, 
     new BasicConstraints(false)) 
    .addExtension(
     new ASN1ObjectIdentifier("2.5.29.15"), 
     true, 
     new X509KeyUsage(
      X509KeyUsage.digitalSignature | 
      X509KeyUsage.nonRepudiation | 
      X509KeyUsage.keyEncipherment | 
      X509KeyUsage.dataEncipherment)) 
    .addExtension(
     new ASN1ObjectIdentifier("1.2.3.4"), 
     false, 
     ext.getExtnValue()); 

    // Create and sign the certificate. 
    X509CertificateHolder certHolder = certBldr.build(sigGen); 

    X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC) 
    .getCertificate(certHolder); 
+0

那些額外的字節字節(04 08)是ASN.1編碼的標籤類型和標籤長度。看起來你的BouncyCastle不會在需要的時候剝離它們(在調用ext.getExtnValue()時)或者你使用BouncyCastle錯誤。鑑於它是開源的,「源代碼是最好的文檔」,您可以查看提示的源代碼。 – 2013-05-07 06:29:05

+0

謝謝尤金!我能夠查看源代碼並使用其他方法來完成所需的任務。 – gtrig 2013-05-10 20:43:24

回答

3

嘗試了很多不同的選項後,我認爲不可能使用X509v3CertificateBuilder創建一個具有原始(非ASN.1編碼)值的擴展。 addExtension()方法預期或將輸入值更改爲ASN.1編碼。

然而,在查看Bouncy Castle的X509v3CertificateBuilder在後臺使用的方法的源代碼之後,我找到了一種與其他類一起使用的方法。涉及更多的代碼行,但它非常簡單,並提供了所需的結果。

以下是允許使用原始值自定義擴展的代碼。

// Raw value to place in cert for OID 1.2.3.4. 
    byte[] bytearray = {0, 0, 0, 0, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; 

    // Start creating the certificate beginning with the TBS certificate.  
    V3TBSCertificateGenerator tbsGen = new V3TBSCertificateGenerator(); 
    tbsGen.setSerialNumber(new ASN1Integer(serialNum)); 
    tbsGen.setIssuer(issuer); 
    tbsGen.setStartDate(new Time(new Date(startDate))); 
    tbsGen.setEndDate(new Time(new Date(endDate))); 
    tbsGen.setSubject(new X500Name(dn)); 
    tbsGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(certPubKey.getEncoded())); 
    tbsGen.setSignature(sigGen.getAlgorithmIdentifier()); 

    // The Key Usage extension: 
    X509KeyUsage keyuse = new X509KeyUsage(
    X509KeyUsage.digitalSignature | 
    X509KeyUsage.nonRepudiation | 
    X509KeyUsage.keyEncipherment | 
    X509KeyUsage.dataEncipherment);  
    Extension keyUsageExt = 
    new Extension(
     Extension.keyUsage, 
     true, 
     keyuse.getEncoded()); 

    // The Basic Constraints extension: 
    BasicConstraints basic = new BasicConstraints(false); 
    Extension basicExt = 
    new Extension(
     Extension.basicConstraints, 
     false, 
     basic.getEncoded()); 

    // The Custom extension:  
    ASN1ObjectIdentifier asn1iod = 
    new ASN1ObjectIdentifier("1.2.3.4");  
    Extension customExt = 
    new Extension(
     asn1iod, 
     false, 
     bytearray); 

    Extension[] extArray = {keyUsageExt, basicExt, customExt}; 
    tbsGen.setExtensions(new Extensions(extArray)); 

    // Create the TBS certificate. 
    TBSCertificate tbsCert = tbsGen.generateTBSCertificate(); 

    // Sign the certificate. 
    OutputStream ostream  = sigGen.getOutputStream(); 
    DEROutputStream derOstream = new DEROutputStream(ostream); 
    derOstream.writeObject(tbsCert); 
    ostream.close();  
    byte[] tbsSig = sigGen.getSignature(); 

    // Assemble the full X509 certificate. (TBS + Sig Alg + Sig) 
    ASN1EncodableVector asnVector = new ASN1EncodableVector(); 
    asnVector.add(tbsCert); 
    asnVector.add(sigGen.getAlgorithmIdentifier()); 
    asnVector.add(new DERBitString(tbsSig)); 
    X509CertificateHolder certHolder = 
    new X509CertificateHolder(
     org.bouncycastle.asn1.x509.Certificate.getInstance(new DERSequence(asnVector))); 

    X509Certificate cert = 
    new JcaX509CertificateConverter() 
     .setProvider(BC).getCertificate(certHolder); 
1

證書是ASN.1編碼的,所以擴展值也應該是ASN.1編碼的。 04是OCTET STRING類型,08 - 此八位字符串的長度。 BouncyCastle不知道任何關於擴展數據格式的信息,這很可能是因爲它沒有去掉標籤和長度,而且應該手動解碼數據。

+0

非常感謝Nickolay,但使用此證書的應用程序需要的值是原始的,而不是ASN.1編碼的。我能夠在Bouncy Castle找到其他方法來創造原始價值。 – gtrig 2013-05-11 09:22:50

相關問題