3

Bouncy Castle の X509v3CertificateBuilder Java クラスを使用して、標準の V3 拡張機能を備えた X509 証明書を作成することに成功しました。カスタム拡張機能を使用して証明書を作成しようとしています。

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」になります。

基本的に、この構成を持つ拡張ファイルを使用して OpenSSL で作成されたときに証明書がどのように見えるかと同じように見えるカスタム拡張を使用して、Java で証明書を作成したいと思います。

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

2 に答える 2

4

多くの異なるオプションを試した後、X509v3CertificateBuilder を使用して生の (ASN.1 でエンコードされていない) 値を持つ拡張機能を作成することはできないと思います。addExtension() メソッドは、入力値が ASN.1 でエンコードされていることを期待または変更します。

しかし、X509v3CertificateBuilder がバックグラウンドで使用するメソッドの Bouncy Castle ソース コードを調べたところ、他のクラスでそれを行う方法を見つけました。より多くのコード行が含まれますが、かなり単純で、必要な結果が得られます。

生の値を持つカスタム拡張を許可するコードを次に示します。

  // 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);
于 2013-05-10T20:40:52.017 に答える
1

証明書は ASN.1 でエンコードされているため、拡張値も ASN.1 でエンコードする必要があります。04 は OCTET STRING タイプ、08 - このオクテット文字列の長さです。BouncyCastle は拡張データの形式について何も知りません。おそらくこれがタグと長さを削除しない理由であり、そのデータを手動でデコードする必要があります。

于 2013-05-07T09:30:13.193 に答える