asn1 编码与解码
Posted luoleqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了asn1 编码与解码相关的知识,希望对你有一定的参考价值。
asn1c
本文使用的是asn1c工具,可在github-asn1c下载。
编码
首先定义asn1结构,文件命名为en.asn1
RectangleTest DEFINITIONS ::=
BEGIN
Rectangle ::= SEQUENCE {
height INTEGER, -- Height of the rectangle
width INTEGER -- Width of the rectangle
}
END
执行命令生成编码解码所需的.h和.c文件。
asn1c -fnative-types en.asn1
- -fnative-types:尽可能使用本机的数据类型(int,double),而不要使用复合INTEGER_t,ENUMERATED_t和REAL_t类型。(当然不加也没什么影响)
然后编写编码主函数main.c文件
#include <stdio.h>
#include <sys/types.h>
#include <Rectangle.h> /* Rectangle ASN.1 type */
/*
* This is a custom function which writes the
* encoded output into some FILE stream.
*/
static int
write_out(const void *buffer, size_t size, void *app_key) {
FILE *out_fp = app_key;
size_t wrote;
wrote = fwrite(buffer, 1, size, out_fp);
return (wrote == size) ? 0 : -1;
}
int main(int ac, char **av) {
Rectangle_t *rectangle; /* Type to encode */
asn_enc_rval_t ec; /* Encoder return value */
/* Allocate the Rectangle_t */
rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */
if(!rectangle) {
perror("calloc() failed");
exit(71); /* better, EX_OSERR */
}
/* Initialize the Rectangle members */
rectangle->height = 42; /* any random value */
rectangle->width = 23; /* any random value */
/* BER encode the data if filename is given */
if(ac < 2) {
fprintf(stderr, "Specify filename for BER output
");
} else {
const char *filename = av[1];
FILE *fp = fopen(filename, "wb"); /* for BER output */
if(!fp) {
perror(filename);
exit(71); /* better, EX_OSERR */
}
/* Encode the Rectangle type as BER (DER) */
ec = der_encode(&asn_DEF_Rectangle,
rectangle, write_out, fp);
fclose(fp);
if(ec.encoded == -1) {
fprintf(stderr,
"Could not encode Rectangle (at %s)
",
ec.failed_type ? ec.failed_type->name : "unknown");
exit(65); /* better, EX_DATAERR */
} else {
fprintf(stderr, "Created %s with BER encoded Rectangle
",
filename);
}
}
/* Also print the constructed Rectangle XER encoded (XML) */
xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
return 0; /* Encoding finished successfully */
}
删除converter-example.c文件(这个文件是main函数样例,我们已经自己定义了main函数,如果不删除gcc会报main重复定义错误)。
rm converter-example.c
编译文件
cc -I. -o rdecode *.c
- -I.:指定当前目录为头文件夹。
这里可能会未定义报措,这个是asn1c的bug
我们只要到 /usr/local/share/asn1c/把对应的C文件复制过来就行。
cp /usr/local/share/asn1c/BIT_STRING_oer.c ./
cp /usr/local/share/asn1c/OCTET_STRING_oer.c ./
运行命令生成asn1二进制文件。
./rencode a.asn1
可以看到已经生成了高值为42,宽值为23的asn1二进制文件。
解码
与编码步骤类似,重复部分不再叙述。
编写解码主函数main.c文件
#include <stdio.h>
#include <sys/types.h>
#include <Rectangle.h> /* Rectangle ASN.1 type */
int main(int ac, char **av) {
char buf[1024]; /* Temporary buffer */
Rectangle_t *rectangle = 0; /* Type to decode */
asn_dec_rval_t rval; /* Decoder return value */
FILE *fp; /* Input file handler */
size_t size; /* Number of bytes read */
char *filename; /* Input file name */
/* Require a single filename argument */
if(ac != 2) {
fprintf(stderr, "Usage: %s <file.ber>
", av[0]);
exit(64); /* better, EX_USAGE */
} else {
filename = av[1];
}
/* Open input file as read-only binary */
fp = fopen(filename, "rb");
if(!fp) {
perror(filename);
exit(66); /* better, EX_NOINPUT */
}
/* Read up to the buffer size */
size = fread(buf, 1, sizeof(buf), fp);
fclose(fp);
if(!size) {
fprintf(stderr, "%s: Empty or broken
", filename);
exit(65); /* better, EX_DATAERR */
}
/* Decode the input buffer as Rectangle type */
rval = ber_decode(0, &asn_DEF_Rectangle,
(void **)&rectangle, buf, size);
if(rval.code != RC_OK) {
fprintf(stderr,
"%s: Broken Rectangle encoding at byte %ld
",
filename, (long)rval.consumed);
exit(65); /* better, EX_DATAERR */
}
/* Print the decoded Rectangle type as XML */
xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
return 0; /* Decoding finished successfully */
}
执行命令编译文件
cc -I. -o rdecode *.c
成功解码
参考
以上是关于asn1 编码与解码的主要内容,如果未能解决你的问题,请参考以下文章