如何解析ASN.1对象并使用java中的bouncycastle获取数据

时间:2013-12-06 06:51:58

标签: java x509certificate bouncycastle asn.1

我有一个ASN.1数据,其中包含一些URL信息和证书数据。现在我正在尝试解析数据。我使用的转储方法如下所示。

  private static void dump(ASN1Object obj, StringBuffer buf, int depth)  throws Exception
  {
    indent(buf, depth);
    if (obj == null)
    {
      buf.append("Null").append(NL);

    }
    else if (obj instanceof DERBitString)
    {
          try {

              DERBitString dbr =  (DERBitString)obj;
              Log.e("Testing", "DERBitString length:"+dbr.getBytes().length);

        } catch (Exception e) {
            // TODO: handle exception
            Log.e("Testing", "Exception :"+e);
        }

     // buf.append("DERBitString : ").append(((DERBitString)obj).getBytes().length * 8).append(" bits").append(NL);
      buf.append("DERBitString content111 : ").append(new String(((DERBitString)obj).getBytes())).append(NL);



      cert.write(obj.getEncoded());
    }
    else if (obj instanceof ASN1String)
    {
        Log.i("Testing", "Hashcode:"+obj.hashCode());
        buf.append("ASN1String : ").append(((ASN1String)obj).getString()).append(NL);
        if(numOctString == 1 && sURL == null )
        {
            sURL = ((ASN1String)obj).getString();
        }
        else
        {
            cert.write(obj.getEncoded());
        }
    }
    else if (obj instanceof ASN1UTCTime)
    {
      buf.append("ASN1UTCTime : ").append(((ASN1UTCTime)obj).getTime()).append(NL);
      cert.write(obj.getEncoded());
    }
    else if (obj instanceof ASN1GeneralizedTime)
    {
      buf.append("ASN1GeneralizedTime : ").append(((ASN1GeneralizedTime)obj).getTime()).append(NL);
      cert.write(obj.getEncoded());
    }
    else if (obj instanceof ASN1ObjectIdentifier)
    {
        buf.append("ASN1ObjectIdentifier : ").append((ASN1ObjectIdentifier)obj).append(NL);

        ASN1ObjectIdentifier identifier =  (ASN1ObjectIdentifier)obj;

        cert.write(obj.getEncoded());
        //buf.append("ASN1ObjectIdentifier : ").append(OidMap.get(((ASN1ObjectIdentifier)obj).getId())).append(NL); 
    }
    else if (obj instanceof ASN1Integer)
    {
      buf.append("ASN1Integer : ").append(((ASN1Integer)obj).getValue().toString()).append(NL);
      cert.write(obj.getEncoded());
    }
    else if (obj instanceof ASN1Boolean)
    {
      buf.append("ASN1Boolean : ").append(((ASN1Boolean)obj).isTrue() ? "true" : "false").append(NL);
      cert.write(obj.getEncoded());
    }
    else if (obj instanceof ASN1OctetString)
    {
       numOctString ++;
      buf.append("ASN1OctetString").append(NL);
      ASN1OctetString octObj = (ASN1OctetString)obj;
      try
      {
        ASN1InputStream aIn = new ASN1InputStream(octObj.getOctetStream());
        ASN1Primitive dobj = aIn.readObject();
        dump(dobj, buf, depth + 1);
      }
      catch(Exception e)
      {
        indent(buf, depth + 1);
        //buf.append(ByteArrayUtil.toHexString(octObj.getOctets(), ":")).append(NL);
      }
    }
    else if (obj instanceof ASN1TaggedObject)
    {
      buf.append("ASN1TaggedObject").append(NL);
      dump(((ASN1TaggedObject)obj).getObject(), buf, depth + 1);
    }
    else if (obj instanceof ASN1Sequence)
    {
      buf.append("ASN1Sequence").append(NL);

      Enumeration objs = ((ASN1Sequence)obj).getObjects();
      while (objs.hasMoreElements())
      {
        Object o = objs.nextElement();
        if (o == null || o instanceof DERNull)
        {
          indent(buf, depth + 1);
          //ASN1VectorImpl impl= new ASN1VectorImpl((ASN1Sequence)obj);
          buf.append("DERNull").append(NL);
        }
        else if (o instanceof ASN1Primitive)
        {
          dump((ASN1Primitive)o, buf, depth + 1);
        }
        else
        {
          dump(((ASN1Encodable)o).toASN1Primitive(), buf, depth + 1);
        }
      }
    }
    else if (obj instanceof ASN1Set)
    {
      buf.append("ASN1Set").append(NL);

      Enumeration objs = ((ASN1Set)obj).getObjects();
      while (objs.hasMoreElements())
      {
        Object o = objs.nextElement();
        if (o == null || o instanceof DERNull)
        {
          indent(buf, depth + 1);
          buf.append(NL);
        }
        else if (o instanceof ASN1Primitive)
        {
          dump((ASN1Primitive)o, buf, depth + 1);
        }
        else
        {
          dump(((ASN1Encodable)o).toASN1Primitive(), buf, depth + 1);
        }
      }
    }
    else
    {
        Log.e("Testing", "==================Else case=============");
        Log.e("Testing", "==================obj============="+obj.getEncoded().length);
      buf.append(obj.getClass().getName()).append(NL);
    }      
  }

当我打印StringBuffer时,我得到如下输出。

 ASN1Sequence
   ASN1Sequence
     ASN1String : 1
     ASN1OctetString
       ASN1Sequence
         ASN1String : https://website url(Some StringDta )
         ASN1String : StringDta
         ASN1Sequence
           ASN1OctetString
             ASN1Sequence
               ASN1Sequence
                 ASN1TaggedObject
                   ASN1Integer : 2
                 ASN1Integer : 288799720653653968683086
                 ASN1Sequence
                   ASN1ObjectIdentifier : 1.2.840.113549.1.1.5
                   DERNull
                 ASN1Sequence
                   ASN1Set
                     ASN1Sequence
                       ASN1ObjectIdentifier : 2.5.4.3
                       ASN1String : StringDta
                 ASN1Sequence
                   ASN1UTCTime : 130417071944GMT+00:00
                   ASN1UTCTime : 140417072944GMT+00:00
                 ASN1Sequence
                   ASN1Set
                     ASN1Sequence
                       ASN1ObjectIdentifier : 2.5.4.10
                       ASN1String : StringDta
                   ASN1Set
                     ASN1Sequence
                       ASN1ObjectIdentifier : 2.5.4.3
                       ASN1String : StringDta
                   ASN1Set
                     ASN1Sequence
                       ASN1ObjectIdentifier : 1.2.840.113549.1.9.1
                       ASN1String : StringDta
                 ASN1Sequence
                   ASN1Sequence
                     ASN1ObjectIdentifier : 1.2.840.113549.1.1.1
                     DERNull
                   DERBitString content111 : 0?
 ?

现在如何解析上述数据以获取URL和证书数据等所需数据?

我们如何从上面的输出中识别URL和证书数据?有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

ASN.1编码对象仅包含结构化数据,但不包含每个字段的含义。需要ASN.1模块才能从对象中解码有意义的数据。该模块是一个数据规范,其目的是命名一组类型和(可选)值定义。

例如,这是X.509证书的ASN.1模块:http://tools.ietf.org/html/rfc5280#appendix-A.1

现在,假设您的ASN.1模块定义了此结构

MyData ::= SEQUENCE {
    websiteURL         UTF8String (SIZE (1..MAX)),
    certificate        Certificate,
}

您可以使用以下小代码段解码此对象:

public void decode(byte[] encoding) throws Exception
{
  ASN1Sequence seq = ASN1Sequence.getInstance(encoding);
  String url = DERUTF8String.getInstance(seq.getObjectAt(0)).getString();
  CertificateFactory factory = CertificateFactory.getInstance("X.509");
  byte[] certEnc = seq.getObjectAt(1).toASN1Primitive().getEncoded();
  Certificate cert = factory.generateCertificate(new ByteArrayInputStream(certEnc));
}

更新12月7日

根据您提供的ASN.1解码树,我认为证书包含在第二个Octet字符串对象中:

ASN1Sequence
  ASN1Sequence
    ASN1String : 1
    ASN1OctetString
      ASN1Sequence
        ASN1String : https://website url(Some StringDta )
        ASN1String : StringDta
        ASN1Sequence
          ASN1OctetString
            ASN1Sequence        <-- IMHO the certificate starts here
              ASN1Sequence
                ASN1TaggedObject
                  ASN1Integer : 2
                ASN1Integer : 288799720653653968683086
...

您需要从序列中获取ASN1OctetString对象,获取它包装的byte []并解码证书。

ASN1Sequence seq = ...
ASN1OctetString ostr = ASN1OctetString.getInstance(seq.getObjectAt(0));
byte[] encodedCertificate = ostr.getOctets();
Certificate cert = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(encodedCertificate));

您还可以使用openssl ans1parse命令在ASN.1对象上打印更多详细信息