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


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值