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

问题描述 投票:0回答: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 和证书数据?有人可以帮忙解决这个问题吗?

java x509certificate bouncycastle asn.1
1个回答
0
投票

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

例如,这是 X.509 证书的 ASN.1 模块:https://www.rfc-editor.org/rfc/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解码树我认为证书包含在第二个八位字节字符串对象中:

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 对象的更多详细信息

© www.soinside.com 2019 - 2024. All rights reserved.