title: Unknown tag encountered parsing AttributeCertificate from DER file with BouncyCastle
body: <p>I'm having issues parsing a DER attribute certificate using the BouncyCastle Java API.</p>
  
  <h1>Errors</h1>
  
  <p>Here is the code I'm attempting to use. I first read the cert file as an InputStream named <code>stream</code>, and try to convert it to a Bouncycastle <code>AttributeCertificate</code> object:</p>
  
  <pre><code>ASN1InputStream derIn = new ASN1InputStream(stream);
  ASN1Sequence seq = (ASN1Sequence) derIn.readObject();
  
  AttributeCertificate cert = AttributeCertificate.getInstance(seq); &lt;-- exception here
  ac = new X509AttributeCertificateHolder(cert); 
  </code></pre>
  
  <p>The third line causes an <code>IllegalArgumentException</code>:</p>
  
  <pre><code>IllegalArgumentException: unknown object in getInstance: org.bouncycastle.asn1.ASN1Integer
      at org.bouncycastle.asn1.ASN1Sequence.getInstance(Unknown Source)
      at org.bouncycastle.asn1.x509.IssuerSerial.getInstance(Unknown Source)
      at org.bouncycastle.asn1.x509.Holder.getInstance(Unknown Source)
      at org.bouncycastle.asn1.x509.AttributeCertificateInfo.getInstance(Unknown Source)
      ...
  </code></pre>
  
  <p>Bouncycastle also throws an <code>IOException</code> saying an "unknown tag" has been encountered:</p>
  
  <pre><code>java.io.IOException: unknown tag 28 encountered
      at org.bouncycastle.asn1.ASN1InputStream.buildObject(Unknown Source)
      at org.bouncycastle.asn1.ASN1InputStream.readObject(Unknown Source)
      ...
  </code></pre>
  
  <h1>Analysis</h1>
  
  <p><strong>I've linked the certificate file I'm attempting to parse <a href="https://www.dropbox.com/s/2672eshwb3be62k/e0-check-x509.der?dl=0" rel="nofollow noreferrer">here</a>.</strong> The cert itself was generated using OpenSSL.</p>
  
  <p>The cert also includes the ABAC credential I'm using, which is a simple string:</p>
  
  <pre><code>[some_uuid].experiment_create &lt;- [some_uuid].partner.experiment_create
  </code></pre>
  
  <p>I looked into the "unknown tag 28" and it seems ASN.1 tag 28 denotes a UniversalString. I found online that "the UniversalString type models a Unicode character string implicitly serialized into UTF-32 big endian."</p>
  
  <p>This to me suggested a possible character encoding issue in the cert. But when I looked at the cert file using <code>openssl asn1parse</code>, it seemed fine:</p>
  
  <pre><code>0:d=0  hl=4 l= 660 cons: SEQUENCE          
  4:d=1  hl=4 l= 509 cons: SEQUENCE          
  8:d=2  hl=2 l=   3 cons: cont [ 0 ]        
  10:d=3  hl=2 l=   1 prim: INTEGER           :02
  13:d=2  hl=2 l=   1 prim: INTEGER           :00
  16:d=2  hl=2 l=  13 cons: SEQUENCE          
  18:d=3  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption
  29:d=3  hl=2 l=   0 prim: NULL              
  31:d=2  hl=2 l=  51 cons: SEQUENCE          
  33:d=3  hl=2 l=  49 cons: SET               
  35:d=4  hl=2 l=  47 cons: SEQUENCE          
  37:d=5  hl=2 l=   3 prim: OBJECT            :commonName
  42:d=5  hl=2 l=  40 prim: UTF8STRING        :bf3a72c271f661dae81647a16c1babf3a52da28e
  84:d=2  hl=2 l=  30 cons: SEQUENCE          
  86:d=3  hl=2 l=  13 prim: UTCTIME           :170828213103Z
  101:d=3  hl=2 l=  13 prim: UTCTIME           :270826213103Z
  116:d=2  hl=2 l=  51 cons: SEQUENCE          
  118:d=3  hl=2 l=  49 cons: SET               
  120:d=4  hl=2 l=  47 cons: SEQUENCE          
  122:d=5  hl=2 l=   3 prim: OBJECT            :commonName
  127:d=5  hl=2 l=  40 prim: UTF8STRING        :bf3a72c271f661dae81647a16c1babf3a52da28e
  169:d=2  hl=3 l= 159 cons: SEQUENCE          
  172:d=3  hl=2 l=  13 cons: SEQUENCE          
  174:d=4  hl=2 l=   9 prim: OBJECT            :rsaEncryption
  185:d=4  hl=2 l=   0 prim: NULL              
  187:d=3  hl=3 l= 141 prim: BIT STRING        
  331:d=2  hl=3 l= 183 cons: cont [ 3 ]        
  334:d=3  hl=3 l= 180 cons: SEQUENCE          
  337:d=4  hl=3 l= 144 cons: SEQUENCE          
  340:d=5  hl=2 l=   8 prim: OBJECT            :id-aca-group
  350:d=5  hl=3 l= 131 prim: OCTET STRING      [HEX DUMP]:0C8180626633613732633237316636363164616538313634376131366331626162663361353264613238652E6578706572696D656E745F637265617465203C2D20626633613732633237316636363164616538313634376131366331626162663361353264613238652E706172746E65722E6578706572696D656E745F637265617465
  484:d=4  hl=2 l=  31 cons: SEQUENCE          
  486:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Authority Key Identifier
  491:d=5  hl=2 l=  24 prim: OCTET STRING      [HEX DUMP]:30168014162E4EF6CD52F37CD2EDDFBEA484E70D6CDE9048
  517:d=1  hl=2 l=  13 cons: SEQUENCE          
  519:d=2  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption
  530:d=2  hl=2 l=   0 prim: NULL              
  532:d=1  hl=3 l= 129 prim: BIT STRING        
  </code></pre>
  
  <p>Other programs also seemed to work fine; <code>openssl x509</code> provides this output:</p>
  
  <pre><code>Certificate:
      Data:
          Version: 3 (0x2)
          Serial Number: 0 (0x0)
      Signature Algorithm: sha256WithRSAEncryption
          Issuer: CN=bf3a72c271f661dae81647a16c1babf3a52da28e
          Validity
              Not Before: Aug 28 21:31:03 2017 GMT
              Not After : Aug 26 21:31:03 2027 GMT
          Subject: CN=bf3a72c271f661dae81647a16c1babf3a52da28e
          Subject Public Key Info:
              Public Key Algorithm: rsaEncryption
                  Public-Key: (1024 bit)
                  Modulus:
                      00:c5:d4:35:49:4d:bd:ee:9a:93:51:a4:e1:46:df:
                      46:c0:1e:f6:b1:85:70:4d:31:2b:20:6f:ab:82:16:
                      b4:9d:3e:ea:f3:38:53:e2:7b:be:36:37:f3:11:7f:
                      90:5d:aa:ad:e7:e8:61:3c:46:8d:7a:69:4d:c6:89:
                      e2:f7:07:d9:3f:b0:5d:f7:ee:40:e5:86:48:7b:4c:
                      0e:0f:11:0c:96:41:e6:99:02:17:df:4e:60:3d:d0:
                      42:b5:dc:22:e0:64:6d:ad:17:22:b7:a2:15:ec:dd:
                      89:c2:b4:58:01:64:d7:db:fe:62:1e:c5:40:0c:e0:
                      b9:12:7e:fe:4c:31:65:e6:51
                  Exponent: 65537 (0x10001)
          X509v3 extensions:
              id-aca-group: 
                  ...bf3a72c271f661dae81647a16c1babf3a52da28e.experiment_create &lt;- bf3a72c271f661dae81647a16c1babf3a52da28e.partner.experiment_create
              X509v3 Authority Key Identifier: 
                  keyid:16:2E:4E:F6:CD:52:F3:7C:D2:ED:DF:BE:A4:84:E7:0D:6C:DE:90:48
  
      Signature Algorithm: sha256WithRSAEncryption
           1e:0f:2a:7a:cf:95:77:0f:5c:48:f3:12:c4:b9:8a:5a:d9:b9:
           62:1c:60:0c:a0:13:70:f3:c5:aa:de:6d:6f:92:7f:0d:a2:3b:
           c9:bd:cc:45:6c:4b:21:8d:32:81:8b:af:13:6e:a3:96:18:05:
           3b:83:fb:8c:3b:2a:d8:87:22:56:9e:4b:1d:06:e6:7f:ba:36:
           89:e8:c6:8a:5a:9e:2c:9b:44:5e:19:fe:68:13:12:93:48:df:
           f9:34:42:01:d5:62:c1:ca:e4:e2:3b:86:b7:4c:75:ba:60:5b:
           c9:f7:68:9a:b0:b5:1c:33:01:5e:77:c0:7c:13:11:e1:09:67:
           42:dd
  </code></pre>
  
  <p>Based off of these I can't find anything clearly wrong with the certificate. The only clue I could find is in this block of Bouncycastle source code for <a href="https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java" rel="nofollow noreferrer">ASN1InputStream.java</a> which throws the exception I found:</p>
  
  <pre><code>// Build an object given its tag and the number of bytes to construct it from.
      protected ASN1Primitive buildObject(
          int       tag,
          int       tagNo,
          int       length)
          throws IOException
      {
          ...
          if (isConstructed)
          {
              // TODO There are other tags that may be constructed (e.g. BIT_STRING)
              switch (tagNo)
              {
                  case OCTET_STRING:
                      //
                      // yes, people actually do this...
                      //
                      ASN1EncodableVector v = buildDEREncodableVector(defIn);
                      ASN1OctetString[] strings = new ASN1OctetString[v.size()];
  
                      for (int i = 0; i != strings.length; i++)
                      {
                          strings[i] = (ASN1OctetString)v.get(i);
                      }
  
                      return new BEROctetString(strings);
                  case SEQUENCE:
                      if (lazyEvaluate)
                      {
                          return new LazyEncodedSequence(defIn.toByteArray());
                      }
                      else
                      {
                          return DERFactory.createSequence(buildDEREncodableVector(defIn));   
                      }
                  case SET:
                      return DERFactory.createSet(buildDEREncodableVector(defIn));
                  case EXTERNAL:
                      return new DERExternal(buildDEREncodableVector(defIn));                
                  default:
                      throw new IOException("unknown tag " + tagNo + " encountered");
              }
          }
  
          return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
      }
  </code></pre>
  
  <p>It seems support for these "other tags that may be constructed," including tag 28, hasn't been coded in yet, but I'm not sure where my certificate is broken or how to fix the tag.</p>
  
  <p>Could anyone point me in the right direction? Thanks.</p>