背景: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类TBSOrderimport 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类来实现编码
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