我有一个 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 和证书数据?有人可以帮忙解决这个问题吗?
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 对象的更多详细信息