有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

openssl使用Bouncy Castle在Java中创建自定义X509 v3扩展

我已经成功地使用Bouncy Castle的X509v3CertificateBuilder Java类创建了带有标准V3扩展的X509证书。我现在正在尝试创建带有自定义扩展名的证书

我可以使用addExtension(…)创建自定义扩展方法,但是,证书中的结果值不是我想要的。例如,我希望在自定义OID 1.2.3.4“00 00 00 FF FF FF”下的证书中列出这些精确的八位字节。我尝试过的每件事都用ASN1编码将八位字节字符串包装起来,结果是“04 08 00 00 00 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);

共 (2) 个答案

  1. # 1 楼答案

    证书是ASN。1编码,因此扩展值也应为ASN。1编码。04为八位字节字符串类型,08为该八位字节字符串的长度。BouncyCastle对扩展数据的格式一无所知,很可能这就是它不剥离标记和长度的原因,您应该手动解码该数据

  2. # 2 楼答案

    在尝试了许多不同的选项之后,我认为不可能使用X509v3CertificateBuilder创建具有原始(非ASN.1编码)值的扩展。addExtension()方法期望或更改输入值为ASN。1编码

    然而,在查看了X509v3CertificateBuilder在幕后使用的方法的BouncyCastle源代码之后,我找到了一种使用其他类的方法。涉及的代码行更多,但它相当简单,并给出了所需的结果

    下面是允许使用原始值进行自定义扩展的代码

      // 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);