Fork me on GitHub

【协议】ASN.1编码

来自几年前本人写的一篇博客 http://blog.csdn.net/newyf_cun/article/details/13016069

如下使用libtasn1分析asn1的编码规则。

http://www.linuxfromscratch.org/blfs/view/stable/general/libtasn1.html

https://github.com/Distrotech/libtasn1

http://www.gnu.org/software/libtasn1/

 

0.ASN.1的编码规则:

  8  7   6  5  4  3  2  1         +        Length        +       Content 
 -------------------------------------------------------------------------
|Class |X |      Tag    |                                                |
 -------------------------------------------------------------------------           
Class:    
  0 0 Universal
  0 1 Application 
  1 0 Context-speciatic:指Type不需传送,双方约定 IMPLICIT1 1 prviate 
X : 0 ---- primitive   -----指定:content without a Structure 只有 1个Length 1个Content
    1 ---- contructed  -----指定:content with addition structure 
      (如squence,squence of , implicit squence ,implicit squence of )
      (Type , Length ,Content )任意个嵌套T-L-C。
Tag: ASN.1中Tag可能超过5个Bits,但是MMS中不会出现
Length: 指Content的长度。

 

ASN编码时支持如下类型

#define ASN1_TAG_BOOLEAN        0x01  // bool类型
#define ASN1_TAG_INTEGER        0x02  // 整数类型
#define ASN1_TAG_SEQUENCE        0x10  // 结构体类型
#define ASN1_TAG_SET            0x11  // 集合类型
#define ASN1_TAG_OCTET_STRING        0x04 // 16进制表示的字节串
#define ASN1_TAG_BIT_STRING        0x03 
#define ASN1_TAG_UTCTime        0x17  // UTC时间
#define ASN1_TAG_GENERALIZEDTime    0x18
#define ASN1_TAG_OBJECT_ID        0x06
#define ASN1_TAG_ENUMERATED        0x0A
#define ASN1_TAG_NULL            0x05
#define ASN1_TAG_GENERALSTRING        0x1B
#define ASN1_TAG_NUMERIC_STRING        0x12
#define ASN1_TAG_IA5_STRING        0x16
#define ASN1_TAG_TELETEX_STRING        0x14
#define ASN1_TAG_PRINTABLE_STRING    0x13
#define ASN1_TAG_UNIVERSAL_STRING    0x1C
#define ASN1_TAG_BMP_STRING        0x1E
#define ASN1_TAG_UTF8_STRING        0x0C
#define ASN1_TAG_VISIBLE_STRING        0x1A

 

1. 创建模板文件

 bash-2.05$ cat tpl.asn
    PKIX1 { }


    DEFINITIONS IMPLICIT TAGS ::=


    BEGIN


    Dss-Sig-Value ::= SEQUENCE {
         r       INTEGER,
         s       INTEGER
    }


    END

  分析:定义一个结构体,含有两个整形变量r和s。

2. 创建模板值文件

    bash-2.05$ cat value.asn
    dp PKIX1.Dss-Sig-Value


    r 4243
    s 4748

  分析:赋值文件,将r赋值为十进制4243,s赋值十进制4748

3. 将以上模板和值文件asn1编码

bash-2.05$ ./asn1Coding tpl.asn value.asn 
    Parse: done.


    var=dp, value=PKIX1.Dss-Sig-Value
    var=r, value=4243
    var=s, value=4748


    name:NULL  type:SEQUENCE
      name:r  type:INTEGER  value:0x1093
      name:s  type:INTEGER  value:0x128c


    Coding: SUCCESS


    -----------------
    Number of bytes=10
    30 08 02 02 10 93 02 02 12 8c 
    -----------------


    OutputFile=value.out


    Writing: done.

  

  分析:asn编码后的数据是30 08 02 02 10 93 02 02 12 8c

  其中:十六进制30 = 二进制0011 0000, 表示通用模式(00)的结构体(1)定义(二进制10000=十六进制0x10) #define ASN1_TAG_SEQUENCE0x10;

  08表示长度为8,即02 02 10 93 02 02 12 8c的长度正好是8;

  02 02 10 93是变量r的类型02(整形#define ASN1_TAG_INTEGER0x02)-长度(02,即值0x10 93的长度)-和值(十六进制10 93转成十进制为4243);

  02 02 12 8c是变量s的类型02(整形#define ASN1_TAG_INTEGER0x02)-长度(02,即值0x12 8c的长度)-和值(十六进制12 8c转成十进制为4748);

4. 将以上输出asn1解码

bash-2.05$ ./asn1Decoding tpl.asn value.out PKIX1.Dss-Sig-Value
    Parse: done.


    Decoding: SUCCESS


    DECODING RESULT:
    name:NULL  type:SEQUENCE
      name:r  type:INTEGER  value:0x1093
      name:s  type:INTEGER  value:0x128c

  分析:文件value.out中保存着3008020210930202128c

  按照模板tpl.asn解码结构体PKIX1.Dss-Sig-Value得到变量r和s的值。

 

5. 将asn模板文件转成c代码

bash-2.05$ ./asn1Parser tpl.asn 
    Done.
    bash-2.05$ cat tpl
    tpl.asn         tpl_asn1_tab.c  
    bash-2.05$ cat tpl_asn1_tab.c 
    #if HAVE_CONFIG_H
    # include "config.h"
    #endif


    #include <libtasn1.h>


    const asn1_static_node tpl_asn1_tab[] = {
      { "PKIX1", 536875024, NULL },
      { NULL, 1073741836, NULL },
      { "Dss-Sig-Value", 536870917, NULL },
      { "r", 1073741827, NULL },
      { "s", 3, NULL },
      { NULL, 0, NULL }
    };

  

posted @ 2015-12-16 14:21  Mr.YF  阅读(1767)  评论(0编辑  收藏  举报