java對asn.1格式數據編解碼示例

    工作中用到了asn.1格式數據,所以這裏對asn.1格式的編解碼做一個簡單的介紹,主要通過程序來構建與解析asn.1格式數據。asn.1格式一般分爲三個部分,分別是類型、長度、值,也就是Tag,Length,Value,簡稱TLV格式。

    類型一般分爲以下幾種:

    sequence,也叫集合和結構

    integer,整數

    utf8string,字符串

    boolean,布爾類型

    time,時間類型

    下面構建一個maven項目,引入項目依賴:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-ext-jdk15on</artifactId>
    <version>1.65</version>
</dependency>

    定義一個student的實體類,繼承ASN1Object:

package com.xxx.asn1;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.x509.Time;

public class Student extends ASN1Object {
	
	private ASN1Integer id;
	private DERUTF8String name;
	private ASN1Integer age;
	private Time createDate;
	
	public void setId(ASN1Integer id) {
		this.id = id;
	}
	public void setName(DERUTF8String name) {
		this.name = name;
	}
	public void setAge(ASN1Integer age) {
		this.age = age;
	}
	public void setCreateDate(Time createDate) {
		this.createDate = createDate;
	}
	
	public ASN1Integer getId() {
		return id;
	}
	public DERUTF8String getName() {
		return name;
	}
	public ASN1Integer getAge() {
		return age;
	}
	public Time getCreateDate() {
		return createDate;
	}
	
	public Student() {
		// TODO Auto-generated constructor stub
	}
	
	

	public Student(ASN1Integer id, DERUTF8String name, ASN1Integer age,
			Time createDate) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.createDate = createDate;
	}
	
	@Override
	public ASN1Primitive toASN1Primitive() {
		ASN1EncodableVector vector = new ASN1EncodableVector();
		vector.add(id);
		vector.add(name);
		vector.add(age);
		vector.add(createDate);
		return new DERSequence(vector);
	}

}

    定義一個主類App,來分別構建asn.1和解析asn.1格式數據:

package com.xxx.asn1;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1SequenceParser;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.x509.Time;
import org.bouncycastle.util.encoders.Base64;

public class App {
	
	/**
	 * 構建asn.1
	 */
	public static void buildStudent(){
		Integer id = 1;
    	String name = "buejee";
    	Integer age = 18;
    	Time createDate = new Time(new Date());
    	try {
			
    		Student student = new Student(new ASN1Integer(id),
    				new DERUTF8String(name),
    				new ASN1Integer(age),
    				createDate);
    		String data = Base64.toBase64String(student.getEncoded());
    		System.out.println(data);
    		OutputStream out = new FileOutputStream(new File("student.cer"));
    		out.write(data.getBytes());
    		out.flush();
    		out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 解析asn.1
	 */
	public static void resolveStudent(){
		byte[] data = Base64.decode("MB0CAQEMBmJ1ZWplZQIBEhcNMjAwNTE1MTUxNDAzWg==");
		ASN1InputStream ais = new ASN1InputStream(data);
		ASN1Primitive primitive = null;
		try {
			while((primitive=ais.readObject())!=null){
				System.out.println("sequence->"+primitive);
				if(primitive instanceof ASN1Sequence){
					ASN1Sequence sequence = (ASN1Sequence)primitive;
					ASN1SequenceParser parser = sequence.parser();
					ASN1Encodable encodable = null;
					while((encodable=parser.readObject())!=null){
						primitive = encodable.toASN1Primitive();
						System.out.println("prop->"+primitive);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				ais.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
    public static void main( String[] args ){
    	//buildStudent();
    	resolveStudent();
    }
}

    分別運行兩個方法,第一個是buildStudent()是構建一個asn.1格式數據,我們最後將他轉爲base64字符串,打印並存儲在student.cer文件中。

     

    打印的結果和保存在student.cer中的結果是一樣的。我們可以通過asn1view工具查看這個內容:

    sequence部分:

    

    第一個integer:

    

    string:

    

    第二個integer:

    

      time :

     

    這所有的內容都符合我們在代碼中定義的數據:

     

    id=1,name=buejee,age=18,createDate=(20)20/05/15 15:36:43,時間是世界時間,所以東八區的話應該是(20)20/05/15 23:36:43,都是正確的。

    我們再來看看解析,調用resolveStudent()方法,控制檯打印結果如下:

    

    數據讀出來了。跟我們構建時傳入的參數一樣。

    本文的代碼和工具asn1view都會放到github上,有需要的可以查看。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章