这篇博客是参照ASN.1 Java编译器使用入门这篇介绍来的。安装插件以及下载运行时环境都是必须的,前面一篇博客介绍了,直接在java语言中定义asn.1实体类,这里,从asn文件开始,通过编译生成java类,然后通过asnrt环境来进行asn.1编解码的工作。
1、在eclipse中安装asn.1插件,这样,就可以创建asn.1的工程和模块了。打开eclipse,依次选择Help->Install New Software->填入 :http://www.asnlab.com/updates,回车,选择sdk和plugin。如果只用java,在sdk中可以只选择与java相关的sdk。
2、一路next,accept,finish等待安装,如果失败,重新安装几次。
3、注意一点,这个工具不是免费的,但是可以试用,试用期间,注册一个license。最后,通过邮件的形式发送给你,将邮箱中的license粘贴到Windows->Preferences->ASN.1->Compiler->ASN.1 Java Compiler->Serial Number这里。
4、安装完成会提示重启eclipse,重启之后,新建->Other->ASN.1->ASN.1 Project。
5、新建->ASN.1 Module
6、编写asn文件。
MyStudent.asn
MyStudent DEFINITIONS AUTOMATIC TAGS ::= BEGIN
EXPORTS Student;
IMPORTS ;
Student ::=SEQUENCE{
id INTEGER,
name VisibleString (FROM("a".."z"|"A".."Z"|"0".."9"|"./-_~%#")),
age INTEGER,
createDate GeneralizedTime
}
mystu Student ::= {
id 1,
name "buejee",
age 18,
createDate "20200519225445z"
}
END
通过安装的插件,我们在编写完成asn文件之后,在Outline视图里面可以清楚的看到MyStudent的一些属性:
我们只有看到了Outline里面有我们定义的SEQUENCE以及默认的值,我们的插件才会生成正确的java类文件。生成的类文件会在output文件夹下的java文件夹内,如下所示:
这一步是自动生成java文件,也就是说我们在保存完asn文件之后,插件会自动生成,如果没有生成,我们可以查看Outline视图,是否正确显示了我们定义的内容,也可以点击Project->Build Automatically。
7、前面我们安装的插件只是在eclipse中可以编译asn生成java文件,还需要下载asnrt.jar就是运行时环境。
8、新建一个普通的工程,加入step7中下载的asnrt.jar到项目buildpath中,另外把我们在step6中生成的java文件加入到项目中,可以改变目录,也可以默认,根据需要来设置,如果改变目录,还需要手动改变他的package。这时候会提示缺少javax.validation的依赖,可以根据提示将其加入到buildpath中。项目结构如下所示:
9、接下来我们就可以进行asn.1编解码的工作了,因为我们在asn文件中定义的exports是Student,所以我们操作的主要类就是Student,而且它本身就已经包含了编解码的方法:ber_encode,ber_decode
编写StudentTest.java
package MyStudent;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class StudentTest {
public static void main(String[] args) {
try {
Student stu = Student.mystu;
ByteArrayOutputStream out = new ByteArrayOutputStream();
stu.ber_encode(out);
byte[] data = out.toByteArray();
for(int i=0;i<data.length;i++) {
System.out.printf("%02X", data[i] & 0xFF);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行程序,打印结果为:301F80010181066275656A6565820112830F32303230303531393232353434355A 。这个结果可以按照TLV的格式,拆成如下:
30 1F -- sequence
80 01 01 -- id
81 06 62 75 65 6A 65 65 -- name
82 01 12 -- age
83 0F 32 30 32 30 30 35 31 39 32 32 35 34 34 35 5A -- createDate
通过这个拆解的16进制,我们也能大概看出这个结果基本是符合我们定义的mystu的值的。
我们可以通过一个在线decode程序验证这个编码:
可以很清楚的看到,我们解码的结果与我们在asn文件中定义的是一致的,id=1,name=buejee,age=18(0x12),
createDate=20200519225445Z。
10、最后解码工作,其实就是根据step9中打印的16进制结果,进行decode即可,还是调用Student类的静态方法ber_decode(),只不过这时候需要传入一个ByteArrayInputStream对象。解析的结果,应该和我们通过在线工具解析的一致,这里不再编码演示。