Android ASN.1 组合类型为Set的结构数据生成及解析
程序员文章站
2022-06-04 10:38:37
...
一、ASN.1简介
ASN.1 – Abstract Syntax Notation dot one。
描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序。
ASN.1只包含信息结构,不处理具体业务数据,它不是一个编程语言。
二、用到的类型说明
类型 | 含义 |
INTEGER | 全部整数(包含正数和负数) |
PrintableString | 字符串 |
Time | 日期 |
OctetString | 字节串 |
Set | 由不同类型的值组成的无序结构 |
三、案例
统计班级同学信息。
首先在build.gradle中导入BC库文件
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.66'
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.66'
设计结构类型的实体类Student:
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.x509.Time;
public class Student extends ASN1Object {
private ASN1Integer Version;
private DERSet set;
public Student(ASN1Integer Version, DERSet set) {
this.Version = Version;
this.set = set;
}
public void setVersion(ASN1Integer Version) {
this.Version = Version;
}
public ASN1Integer getVersion() {
return Version;
}
public DERSet getSet() {
return set;
}
@Override
public ASN1Primitive toASN1Primitive() {
ASN1EncodableVector vector = new ASN1EncodableVector();
vector.add(Version);
vector.add(set);
return new DERSequence(vector);
}
public static class StudentElement extends ASN1Object{
private ASN1Integer id;
private DERPrintableString name;
private ASN1Integer age;
private Time createDate;
private DEROctetString heigh;
public void setId(ASN1Integer id) {
this.id = id;
}
public void setName(DERPrintableString name) {
this.name = name;
}
public void setAge(ASN1Integer age) {
this.age = age;
}
public void setCreateDate(Time createDate) {
this.createDate = createDate;
}
public void seHeigh(DEROctetString heigh) {
this.heigh = heigh;
}
public ASN1Integer getId() {
return id;
}
public DERPrintableString getName() {
return name;
}
public ASN1Integer getAge() {
return age;
}
public Time getCreateDate() {
return createDate;
}
public DEROctetString getHeigh() {
return heigh;
}
public StudentElement() {
// TODO Auto-generated constructor stub
}
public StudentElement(ASN1Integer id, DERPrintableString name, ASN1Integer age,
Time createDate, DEROctetString heigh) {
super();
this.id = id;
this.name = name;
this.age = age;
this.createDate = createDate;
this.heigh = heigh;
}
@Override
public ASN1Primitive toASN1Primitive() {
ASN1EncodableVector vector = new ASN1EncodableVector();
vector.add(id);
vector.add(name);
vector.add(age);
vector.add(createDate);
vector.add(heigh);
return new DERSequence(vector);
}
}
}
使用:
/**
* 构建asn.1
*/
public static void buildStudent(){
Integer id = 1;
String name = "alex";
Integer age = 18;
Time createDate;
byte[] bytes = new byte[]{0x12,0x34};
try {
ASN1Encodable[] element = new ASN1Encodable[3];
for (int i = 0; i < 3; i++) {
createDate = new Time(new Date());
Student.StudentElement studentElement = new Student.StudentElement(new ASN1Integer(i),
new DERPrintableString(name + "_" + i),
new ASN1Integer(age),
createDate,
new DEROctetString(bytes)
);
element[i] = studentElement;
}
Student student = new Student(new ASN1Integer(1), new DERSet(element));
String data = Base64.toBase64String(student.getEncoded());
System.out.println("asn.1 -> " + data);
// OutputStream out = new FileOutputStream(new File("student.cer"));
// out.write(data.getBytes());
// out.flush();
// out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
运行结果:
hex字符串:
306E020101316930210201001306616C65785F30020112170D3230313033303036313634325A0402123430210201011306616C65785F31020112170D3230313033303036313634325A0402123430210201021306616C65785F32020112170D3230313033303036313634325A04021234
base64后字符串:
MG4CAQExaTAhAgEAEwZhbGV4XzACARIXDTIwMTAzMDA2MTY0MloEAhI0MCECAQETBmFsZXhfMQIBEhcNMjAxMDMwMDYxNjQyWgQCEjQwIQIBAhMGYWxleF8yAgESFw0yMDEwMzAwNjE2NDJaBAISNA==
解析工具,解析结果:
四、总结
ASN.1结构对于我来说了解普通使用就够用了,对于结构的解析网上案例很多,我就不再多余了。如果有需要再增加解析吧。
我还找了一些拆分hex字符串的文章看,里边有介绍数据头是以3080为界,大于3080 的8后为数据长度的长度,小于3080,30后就是数据长度。比如 3081024365:4365为数据, 02是数据的长度,81中的1表示长度是一个字节,30为头。再比如30820132xxxxx:xxxx(太长用x表示不是完整数据)是数据,0123是数据长度,82中的2表示长度是两个字节,30为头。