BouncyCastle的ASN.1編碼功能探究
阿新 • • 發佈:2019-01-10
背景: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
3、實現一個OrderGenerator類來實現編碼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); } }
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