使用Java解析ASN.1二进制数据

23

我有一些二进制ASN.1数据对象需要解析到我的Java项目中。我只需要像BER Viewer一样解析的ASN.1结构和数据:

在BER Viewer中显示的ASN.1结构

BouncyCastle的ASN.1解析器无法解析此结构(仅返回应用程序特定的二进制数据类型)。

我可以使用哪个ASN.1库来获得这样的结果?是否有人有演示如何解析ASN.1对象的示例代码?

顺便说一句:我还尝试了几个免费的ASN.1 Java编译器,但是没有一个能够生成给定ASN.1规范的工作Java代码。


你是想解析一串BER数据流,还是要实现一个特定的ASN.1语法? - Tom Anderson
我有一个ASN.1语法,但我测试过的ASN.1编译器都不接受它。无论如何,我更喜欢不受限于我拥有语法的那些对象。 - Robert
5个回答

21

我需要更正 - 使用BouncyCastle中包含的ASN.1解析器是可以读取数据的,然而这个过程并不简单。

如果你只想打印出包含在ASN.1结构中的数据,我建议你使用类org.bouncycastle.asn1.util.ASN1Dump。它可以通过以下简单的代码片段使用:

ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(data));
ASN1Primitive obj = bIn.readObject();
System.out.println(ASN1Dump.dumpAsString(obj));

它打印结构但不打印数据 - 但是通过将ASN1Dump复制到自己的类中并修改以打印例如OCTET_STRINGS,这可以轻松完成。

此外,ASN1Dump中的代码演示了解析ASN.1结构的方法。例如,可以使用以下代码将用于我的问题的数据解析一级更深:

DERApplicationSpecific app = (DERApplicationSpecific) obj;
ASN1Sequence seq = (ASN1Sequence) app.getObject(BERTags.SEQUENCE);
Enumeration secEnum = seq.getObjects();
while (secEnum.hasMoreElements()) {
    ASN1Primitive seqObj = (ASN1Primitive) secEnum.nextElement();
    System.out.println(seqObj);
}

7
只需使用“true”来打印值。
    ASN1InputStream ais = new ASN1InputStream(
        new FileInputStream(new File("d:/myfile.cdr")));
    while (ais.available() > 0) {
        ASN1Primitive obj = ais.readObject();
        System.out.println(ASN1Dump.dumpAsString(obj, true));
    }
    ais.close();

仅供信息目的:具有两个参数的dumpAsString在较旧版本的bouncycastle中不可用。 - kukudas

3
从您的问题中并不清楚您是否拥有您正在尝试解析的BER的ASN.1规范。请注意,如果在生成它的ASN.1规范中使用了显式标记,则没有ASN.1规范,您只能部分理解数据。一些工具(如OSS Nokalva的工具)具有名为JIAAPI的库(jar文件),可以让您遍历和操作BER编码,而无需事先了解ASN.1规范。
如果您有ASN.1规范,任何ASN.1 Java编译器都应该能够处理此问题。
您可以从http://www.oss.com/asn1/products/asn1-download.html下载OSS ASN.1 Tools for Java的免费试用版,以查看它是否比您之前不成功尝试的其他工具更好用。

2
我需要能够在krypt中解析任何类型的ASN.1数据。虽然krypt是一个Ruby项目,但您可能想看一下JRuby扩展 - 用于处理ASN.1解析/编码的代码完全是用Java编写的,且模块化程度足够方便提取。
我还制作了仅限Java版本,但它缺少前者的某些高级功能。但由于它很简洁,也许这是一个不错的入门机会。

你的代码看起来很不错 - 不幸的是,我注意到我不仅需要一个ASN.1解析器/反序列化器,还需要序列化部分。 - Robert
谢谢!当我开始将Java版本集成到krypt中时,我停止了Java-only版本的更新。在那里,您还将找到序列化位。整个impl包是自包含的,因此它不会与JRuby特定内容混合-您应该能够轻松提取它。 - emboss

1

5
注意:com.sun.* 包中的 JDK 类不是公共 API,可能会在未来版本中被移除或更改。 - Puce
@Tom:我会尝试使用这些类,但是这些类的文档和其他几个ASN.1项目的文档一样糟糕:几乎不存在... - Robert
文档不是很理想,但类很简单,你可以通过OpenJDK获取源代码。我想通过阅读和实验,你可以学到你需要知道的一切。 - Tom Anderson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接