zoukankan      html  css  js  c++  java
  • 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
    

    成功解码

    参考

    github asn1c

  • 相关阅读:
    ES6/ES2015核心内容(上)
    集合转数组的toArray()和toArray(T[] a)方法
    重复输出一个给定的字符串
    10道典型的JavaScript面试题
    用 JavaScript 检测浏览器在线/离线状态(JavaScript API — navigator.onLine)
    List<实体>与List<String>数据互转
    CSS实现四种loading动画效果
    Windows上安装Mac OS
    Android应用层View绘制流程之measure,layout,draw三步曲
    推断输入信息是否为空
  • 原文地址:https://www.cnblogs.com/luoleqi/p/12769690.html
Copyright © 2011-2022 走看看