1. 程式人生 > >BouncyCastle的ASN.1編碼功能探究

BouncyCastle的ASN.1編碼功能探究

背景:BouncyCastle 是一種用於 Java平臺的開放原始碼的輕量級密碼術包。。。(省略500字);ASN.1是一種 ISO/ITU-T 標準,描述了一種對資料進行表示、編碼、傳輸和解碼的資料格式。。。(省略500字)。

本次例項利用BouncyCastle庫實現一個訂單的ASN1編碼,訂單資訊包括訂單號、商品名稱、商品數量、總金額、訂單生產時間等(只是為了測試,所以就簡單了些)。

1、  定義ASN.1資料結構

TBSOrder::= SEQUENCE{
orderId INTEGER,--訂單號
itemName UTF8String,--商品名稱
number INTEGER,--商品數量
amount REAL,--總金額
genTime Time—訂單生產時間
 }

2、  實現對應的java類TBSOrder

import java.util.Enumeration;

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

public class TBSOrder extends ASN1Object {

        private ASN1Sequence tbsOrderSeq;
	private DERInteger orderId;//訂單號
	private DERUTF8String itemName;//商品名稱
	private DERInteger number;//商品數量
	private DERUTF8String amount;//總金額(樓主實在不知道REAL該對應什麼型別,暫定位DERUTF8String吧)
	private Time genTime;//訂單生產時間
       /** 所有成員的get、set方法略 **/	
        。。。 。。。 。。。

	public TBSOrder() {
		super();
	}

	public TBSOrder(DERInteger orderId, DERUTF8String itemName,
			DERInteger number, DERUTF8String amount, Time genTime) {
		super();
		this.orderId = orderId; 
		this.itemName = itemName;
		this.number = number;
		this.amount = amount;
		this.genTime = genTime;
	}
	
	@SuppressWarnings("unchecked")
	private TBSOrder(ASN1Sequence tbsOrderSeq) {
		this.tbsOrderSeq = tbsOrderSeq;
		Enumeration<Object> emu = this.tbsOrderSeq.getObjects();
		orderId = (DERInteger) emu.nextElement();//順序狠重要
		itemName = (DERUTF8String) emu.nextElement();
		number = (DERInteger) emu.nextElement();
		amount = (DERUTF8String) emu.nextElement();
		genTime = Time.getInstance(emu.nextElement());
	}
	
	public static TBSOrder getInstance(Object obj) {
		if (obj instanceof TBSOrder) {
			return (TBSOrder) obj;
		} else if (obj != null) {
			return new TBSOrder(ASN1Sequence.getInstance(obj));
		}
		return null;
	}

	@Override
	public ASN1Primitive toASN1Primitive() {
		ASN1EncodableVector vector = new ASN1EncodableVector();
		vector.add(this.orderId); //順序狠重要,必須和上面的一致
		vector.add(itemName);
		vector.add(number);
		vector.add(amount);
		vector.add(genTime);
		return new DERSequence(vector);
	}

}
3、實現一個OrderGenerator類來實現編碼
importjava.util.Date;

importorg.bouncycastle.asn1.DERInteger;
importorg.bouncycastle.asn1.DERUTF8String;
importorg.bouncycastle.asn1.x509.Time;

publicclass OrderGenerator {

public static void main(String[] args) {

           Integer orderId = 1;
           String itemName = "蘋果";
           int number = 3;
           float amount = 15.0f;
           Time genTime = new Time(new Date());
           try {
                    TBSOrder tbsOrder = newTBSOrder(
                                       newDERInteger(orderId),
                                       newDERUTF8String(itemName),
                                       newDERInteger(number),
                                       newDERUTF8String(String.valueOf(amount)),
                                       genTime);
                    //將結果進行b64編碼
                    String orderB64 =Base64Utils.encodeBase64(tbsOrder.toASN1Primitive().getEncoded());
                    System.out.println("result:"+ orderB64);
           } catch (Exception e) {
                    e.printStackTrace();
           }
}
}

輸出結果:MCMCAQEMBuiLueaenAIBAwwEMTUuMBcNMTQxMjEyMDU0NjM5Wg==

可以將上述結果放到一個txt檔案中,重新命名為order.cer,然後用asn1編碼檢視工具進行檢視(如asn1View),如圖:

4、附上Base64Utils類的程式碼,(實現b64編碼)

/**
 * <p>Title: Base64加密基礎類</p>
 * <p>Description: 進行Base64加密解密操作</p>
 */

public class Base64Utils {
    private static final int fillchar = '=';
    private static final String cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                    + "abcdefghijklmnopqrstuvwxyz"
                                    + "0123456789+/";
    public Base64Utils() {
    }

  
    /**
     * Encodes a String as a base64 String.
     * @param data a String to encode.
     * @return a base64 encoded String.
     */
    public static String encodeBase64(String data) {
        return encodeBase64(data.getBytes());
    }

    /**
     * Encodes a byte array into a base64 String.
     *
     * @param data a byte array to encode.
     * @return a base64 encode String.
     */
    public static String encodeBase64(byte[] data) {
        int c;
        int len = data.length;
        StringBuffer ret = new StringBuffer(((len / 3) + 1) * 4);
        for (int i = 0; i < len; ++i) {
            c = (data[i] >> 2) & 0x3f;
            ret.append(cvt.charAt(c));
            c = (data[i] << 4) & 0x3f;
            if (++i < len)
                c |= (data[i] >> 4) & 0x0f;

            ret.append(cvt.charAt(c));
            if (i < len) {
                c = (data[i] << 2) & 0x3f;
                if (++i < len)
                    c |= (data[i] >> 6) & 0x03;

                ret.append(cvt.charAt(c));
            }
            else {
                ++i;
                ret.append((char) fillchar);
            }

            if (i < len) {
                c = data[i] & 0x3f;
                ret.append(cvt.charAt(c));
            }
            else {
                ret.append((char) fillchar);
            }
        }
        return ret.toString();
    }

    /**
     * Decodes a base64 String.
     *
     * @param data a base64 encoded String to decode.
     * @return the decoded String.
     */
    public static String decodeBase64(String data) {
        return decodeBase64(data.getBytes());
    }

    /**
     * Decodes a base64 aray of bytes.
     *
     * @param data a base64 encode byte array to decode.
     * @return the decoded String.
     */
    public static String decodeBase64(byte[] data) {
        int c, c1;
        int len = data.length;
        StringBuffer ret = new StringBuffer((len * 3) / 4);
        for (int i = 0; i < len; ++i) {
            c = cvt.indexOf(data[i]);
            ++i;
            c1 = cvt.indexOf(data[i]);
            c = ((c << 2) | ((c1 >> 4) & 0x3));
            ret.append((char) c);
            if (++i < len) {
                c = data[i];
                if (fillchar == c)
                    break;

                c = cvt.indexOf((char) c);
                c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
                ret.append((char) c1);
            }

            if (++i < len) {
                c1 = data[i];
                if (fillchar == c1)
                    break;

                c1 = cvt.indexOf((char) c1);
                c = ((c << 6) & 0xc0) | c1;
                ret.append((char) c);
            }
        }
        return ret.toString();
    }
}

最後附上用到的jar包和工具

Asn1View工具下載地址:http://download.csdn.net/detail/suibianok123/8251941

Bouncycastle庫下載地址:http://www.bouncycastle.org/latest_releases.html