在进行简单结构体的编码解码之前我们先来了解一下什么是ASN.1?什么是DER?什么是TLV?
01 ASN.l抽象语法标记ASN.1
抽象语法标记(Abstract Syntax Notation One) ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序。
ASN.1是描述在网络上传输信息格式的标准方法。它有两部分:一部分描述信息内数据,数据类型及序列格式;另一部分描述如何将各部分组成消息。它原来是作为X.409的一部分而开发的,后来才自己独立成为一个标准。ASN.1在OSI的ISO 8824/ITU X.208(说明语法)和ISO 8825/ITU X.209(说明基本编码规则)规范。
例如:
Report ::= SEQUENCE {
author OCTET STRING,
title OCTET STRING,
body OCTET STRING,
biblio Bibliography
}
在这个例子中,"Report"是由名字类型的信息组成的,而SEQUENCE表示消息是许多数据单元构成的,前三个数据单元的类型是OCTET STRING,而最后一个数据类型见下面的ASN.1语法表示它的意义:
Bibliography ::= SEQUENCE {
author OCTET STRING
title OCTET STRING
publisher OCTET STRING
year OCTET STRING
}
ASN.1中定义的数据类型既有简单的基本数据类型,也有复杂的结构类型。
- 基本类型是不可再再分的,包括:
o 布尔型(BOOLEAN)
o 整型(INTEGER)
o 实型(REAL)
o 位串类型(BITSTRING)
o 8位位组类型(OCTET STRING)
o 枚举类型(ENUMERATED)
o 空类型(NULL)
o 对象标识符(OBJECT IDENTIFIER) - 除基本类型,ASN.1还定义了多种复杂的结构类型,例如:
o SEQUENCE:有序的数据集合(序列),由不同类型的数据组成。SEQUENCE结构强调内部成员的排序
o SEQUENCE OF:有序的数据集合,类似于C语言的数组,由同一类型的数据组成。
o SET:由不同类型的数据组成的集合,用来描述复杂的信息对象,对内部成员的顺序不作要求,类似于C语言的结构体类型
o CHOICE:选择结构,在列出的内部成员中,只能选择其中之一,类似于C语言中的共用体类型
ASN.1可以实现跨平台的编码解码的结果唯一性。
02 BER编码规则
DER报文编码方式,唯一标识符编码,消除二义性。
001 基本规则
002 样例及原理
比如对老师的结构体进行编码:
typedef struct _Teacher
{
char name[64];
int age ;
char *p;
}Teacher;
假设:
Teacher.name是myname,标签是10,长度是7;
Teacher.age是25岁,标签是11,长度是4;
Teacher—>p所指的内容是 aaaaaaa,标签是12,长度是1024;
一般编码之前不管是Java类还是C/C++写的结构体都会先转成ASN.1语法,然后进行统一编码。
Teacher::=SEQUENCE{
name OCTET STRING
age INTERGER
p OCTET STRING
}
然后看下图对其进行编码:
03 实现简单结构体的编码解码
在这个案例中,我们对于结构体的编码解码调用开源的DER编码,解码的API函数,如下:
这个后面会上传上来
(一般在工程开发中也是这样做,现在模拟一个简单的工程开发,对老师的结构体进行编码,解码操作,然后对比编码前和解码后的value是否一样)
01_简单结构体编码解码.c
#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "itcast_asn1_der.h"
#include "itcastderlog.h"
typedef struct _Teacher
{
char name[64];
int age;
char *p;
int plen;
}Teacher;
int mywritefile(unsigned char *buf, int len)
{
FILE *fp = NULL;
fp = fopen("c:/teacher.ber", "wb+");
if (fp == NULL)
{
printf("fopen file error \n");
return -1;
}
fwrite(buf, 1, len, fp);
fclose(fp);
return 0;
}
/*
typedef struct ITCAST_ANYBUF_{
unsigned char *pData;
ITCAST_UINT32 dataLen;
ITCAST_UINT32 unusedBits; // for bit string
ITCAST_UINT32 memoryType;
ITCAST_UINT32 dataType;
struct ITCAST_ANYBUF_ *next; //for sequence and set
struct ITCAST_ANYBUF_ *prev;
}ITCAST_ANYBUF;
ITCAST_INT
DER_ItAsn1_WritePrintableString(ITASN1_PRINTABLESTRING *pPrintString, ITASN1_PRINTABLESTRING **ppDerPrintString);
*/
//报文编码
int Teacher_Encode(Teacher *pstruct, unsigned char **p, int *len)//一级指针输入,二级指针输出
{
//Teacher_Encode(&t1, &out, &outlen);
int ret = 0;
ITCAST_ANYBUF *pTmp = NULL, *pHeadBuf = NULL;
ITCAST_ANYBUF *pTmpBuf = NULL;
ITCAST_ANYBUF *pOutData = NULL;