ASN.1格式数据编解码总结

    前面写了两篇博客,分别介绍了Java语言如何对asn.1格式数据编解码,都是很基础的,尤其是编码规则也是ber,就是basic encoding rules,所以普通的工具或者语言涉及到asn.1的编解码,很多都能实现,包括javascript都能做到ber的编解码。今天需要对asn.1格式数据做一个总结。

    ASN.1是Abstract Syntax Notation One的简称,就是抽象语法表示法。我们通常所见的一些工具包括asnview,nodejs的依赖asn1都只是对ber编码起作用。

    ASN.1编解码分为以下几种规则:

  •      Basic Encoding Rules 基本编码规则
  •      Canonical Encoding Rules 规范编码规则
  •      Distinguished Encoding Rules  识别名编码规则
  •      Packed Encoding Rules 压缩编码规则
  •      XML Encoding Rules XML编码规则

     对于ber编解码规则,连nodejs都有实现的asn1依赖库。而且有个网站:https://lapo.it/asn1js/,他好像能在线解码ber编码,好像无法解析uper编码。BER采用了最基本的TLV三元组结构对抽象数据进行编解码操作,规则过于简单,编码后的数据开销过大。ber因为太基础,而且编码的效果不是很好,所以一般不会在实际中使用。

    CER和DER两种编码规则均在BER的基础上增加了一定的约束发展而来。他们的区别在于:CER使用不定长编码格式,满足了传输大量数据的需要,能够保证在所有数据没有到达的时候就开始编解码的工作;DER使用了定长编码格式为可靠数据的传输而设计,主要用于对安全性要求比较高的应用程序。

     值得一提的是,我们通常见到最多的der编码规则的就是各种网站的证书certification。

    

     而我们在数据传输类协议中,通常使用PER编码,他采用了有效算法,缩短了编解码的时间。与BER规则相比,PER编码后数据占用空间能够获得40%-50%的改进,因此被广泛使用于VoIP、视频电话、多媒体以及移动通信系统等高速数据传输领域。

    前面写了一篇博客是在java语言中通过bouncycastle提供的asn编解码依赖,只能对BER规则进行编解码。如果是UPER规则,那么就需要asnlab的支持了,他提供了一套支持c,c++,java等多种语言,多种编解码方式的asn1解决方案。但是如果从asn文件生成java类或者c类需要证书,免费证书可以试用一个月。而运行时环境asnrt可以在该网站下载。

    如下所示,我的asn1插件可以设置几种编解码方法,一般应用,选择一个就够了:

    

    生成的java类如下所示:

     

     这里编解码,会多出一个参数,按照要求,如果是UPER解码,我们这里就是调用per_decode(false,in);截图看的不是很清楚,把代码粘出来:  

public static Student per_decode(boolean align, InputStream in) throws IOException {
		return (Student)TYPE.decode(in, align? 
            EncodingRules.ALIGNED_PACKED_ENCODING_RULES:
            EncodingRules.UNALIGNED_PACKED_ENCODING_RULES, 
        CONV);
}

    这里的编码规则有aligned_packed_encoding_rules与unaligned_packed_encoding_rules两种,我们根据需要传入(false,in)就可以进行对应的UPER解码了。 

    另外,推荐一个比较全面的在线编译asn文件以及对各种编码规则进行编解码的网站:https://asn1.io/asn1playground/,可以在线编译asn文件,然后根据设置的值进行编码,也可以根据编码结果进行解码。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Android上使用ASN.1编解码,可以采用Bouncy Castle库提供的API实现。 首先,需要在项目中导入Bouncy Castle库,可以通过Gradle添加以下依赖: ``` implementation 'org.bouncycastle:bcprov-jdk15on:1.68' implementation 'org.bouncycastle:bcpkix-jdk15on:1.68' ``` 接下来,可以使用Bouncy Castle提供的ASN.1编解码API实现对ASN.1格式数据编解码。下面是一个简单的示例代码: ```java import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1OutputStream; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class ASN1Util { /** * 将ASN.1格式数据编码为字节数组 * * @param data 编码前的数据 * @return 编码后的数据 * @throws IOException */ public static byte[] encode(byte[] data) throws IOException { // 构造ASN.1格式数据 DERSequence seq = new DERSequence(new ASN1Primitive[]{ new DERInteger(123), new DEROctetString(data) }); // 将ASN.1格式数据编码为字节数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ASN1OutputStream os = new ASN1OutputStream(baos); os.writeObject(seq); os.close(); return baos.toByteArray(); } /** * 将字节数组解码为ASN.1格式数据 * * @param encodedData 编码后的数据 * @return 解码后的数据 * @throws IOException */ public static byte[] decode(byte[] encodedData) throws IOException { // 将字节数组解码为ASN.1格式数据 ByteArrayInputStream bais = new ByteArrayInputStream(encodedData); ASN1InputStream is = new ASN1InputStream(bais); DERSequence seq = (DERSequence) is.readObject(); is.close(); // 解析ASN.1格式数据 int intValue = ((DERInteger) seq.getObjectAt(0)).getValue().intValue(); byte[] data = ((DEROctetString) seq.getObjectAt(1)).getOctets(); return data; } } ``` 上述代码中,ASN1Util类提供了encodedecode方法,分别用于将ASN.1格式数据编码为字节数组和将字节数组解码为ASN.1格式数据。在encode方法中,首先构造了一个ASN.1格式的序列,包含一个整数和一个字节数组,然后使用ASN1OutputStream将序列编码为字节数组;在decode方法中,首先使用ASN1InputStream将字节数组解码为ASN.1格式数据,然后解析ASN.1格式数据,获取整数和字节数组。 使用示例: ```java byte[] data = "hello, world!".getBytes(); byte[] encodedData = ASN1Util.encode(data); byte[] decodedData = ASN1Util.decode(encodedData); System.out.println(new String(decodedData)); // 输出:hello, world! ``` 这样,就可以使用Bouncy Castle库在Android上实现ASN.1编解码了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值