ASN1编解码实现

头文件

#ifndef ASN1_H
#define ASN1_H

#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif

/* asn1 types */
typedef enum
{
    ASN1_TAG_Boolean            = 0x01,
    ASN1_TAG_Interger            = 0x02,
    ASN1_TAG_BitString            = 0x03,
    ASN1_TAG_OctetString        = 0x04,
    ASN1_TAG_Null                = 0x05,
    ASN1_TAG_ObjectIdentifier    = 0x06,
    ASN1_TAG_ObjectDescriptor    = 0x07,
    ASN1_TAG_External            = 0x08,
    ASN1_TAG_Real                = 0x09,
    ASN1_TAG_Enumerated            = 0x0A,
    ASN1_TAG_Embedded            = 0x0B,
    ASN1_TAG_Utf8String            = 0x0C,
    ASN1_TAG_RelativeOID        = 0x0D,
    ASN1_TAG_NumericString        = 0x12,
    ASN1_TAG_PrintableString    = 0x13, // printable subset of ascii
    ASN1_TAG_TeletexString        = 0x14,
    ASN1_TAG_VideotexString        = 0x15,
    ASN1_TAG_IA5String            = 0x16, // 7-bit ascii
    ASN1_TAG_UTCTime            = 0x17,
    ASN1_TAG_GeneralizedTime    = 0x18,
    ASN1_TAG_GraphicString        = 0x19,
    ASN1_TAG_VisibleString        = 0x20,
    ASN1_TAG_GeneralString        = 0x21,
    ASN1_TAG_UniversalString    = 0x22,
    ASN1_TAG_CharacterString    = 0x23,
    ASN1_TAG_BmpString            = 0x24, // 2-byte unicode with zeros
    ASN1_TAG_Sequence            = 0x30,
    ASN1_TAG_Set                = 0x31,
    ASN1_TAG_Explicit_0            = 0xA0,
    ASN1_TAG_Explicit_1            = 0xA1,
    ASN1_TAG_Explicit_2            = 0xA2,
    ASN1_TAG_Explicit_3            = 0xA3,
    ASN1_TAG_Explicit_4            = 0xA4,
    ASN1_TAG_Explicit_5            = 0xA5

}asn1_tag;

typedef struct asn1_value_st
{
    int tag;
    int len;
    unsigned char* data;

    int num;
    struct asn1_value_st* arr;

}asn1_value;

void asn1_init_value(OUT asn1_value* val);
void asn1_free_value(OUT asn1_value* val);

int asn1_decode_value(OUT asn1_value* val, IN const unsigned char* input);

asn1_value* asn1_get_children(IN const asn1_value* val, IN const int index);

typedef enum
{
    False = 0,
    True  = 1
}Boolean;

typedef struct
{
    int len;
    unsigned char* data;

}asn1_string;

typedef Boolean asn1_Boolean;
typedef long long asn1_Interger;
typedef asn1_string asn1_BitString;
typedef asn1_string asn1_OctetString;
typedef asn1_string asn1_ObjectIdentifier;

Boolean asn1_get_Boolean(OUT asn1_Boolean* interger, IN const asn1_value* val);
Boolean asn1_get_Interger(OUT asn1_Interger* interger, IN const asn1_value* val);
Boolean asn1_get_BitString(OUT asn1_BitString* bitstring, IN const asn1_value* val);
Boolean asn1_get_OctetString(OUT asn1_OctetString* octetstring, IN const asn1_value* val);
Boolean asn1_get_ObjectIdentifier(OUT asn1_ObjectIdentifier* objectidentifier, IN const asn1_value* val);
// ... asn1 get other type

int asn1_value_print(IN asn1_value* val, int level);

#endif // ASN1_H
View Code

实现文件

#include "asn1.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void printf_error()
{
    printf("assert_error \n");
}

#define ASSERT_RETURN_NULL(x)    if(!(x)) { printf_error(); return NULL; }
#define ASSERT_RETURN_0(x)        if(!(x)) { printf_error(); return 0; }
#define ASSERT_RETURN_VOID(x)    if(!(x)) { printf_error(); return; }
#define ASSERT_RETURN_FALSE(x)    if(!(x)) { printf_error(); return False; }

#ifndef NULL 
#define NULL ((void *)0)
#endif

void asn1_init_value(OUT asn1_value* val)
{
    ASSERT_RETURN_VOID(val);
    memset(val, 0, sizeof(asn1_value));
}

void asn1_free_value(OUT asn1_value* val)
{
    ASSERT_RETURN_VOID(val);
    if (val->num > 0)
    {
        int i = 0;
        for (i = 0; i < val->num; i++) { asn1_free_value(&val->arr[i]); }
        free(val->arr);
    }
    memset(val, 0, sizeof(asn1_value));
}

int asn1_get_info(OUT int* type, OUT int* len, OUT unsigned char** data, IN const unsigned char* input)
{
    ASSERT_RETURN_0(type);
    ASSERT_RETURN_0(len);
    ASSERT_RETURN_0(data);

    *type = *input++;
    int size = 1;

    if (0 == (*input & 0x80))
    {
        // short form
        *len = *input++;
        size += 1;
    }
    else
    {
        // long form
        int lensize = *input++ & 0x7F;
        size += 1 + lensize;

        *len = 0;
        while (lensize-- > 0)
        {
            *len = (*len << 8) | *input++;
        }
    }

    *data = (*len > 0) ? (unsigned char*)input : NULL;

    return size;
}

asn1_value* asn1_add_value(IN asn1_value* parent)
{
    if (7 == parent->num)
    {
        int x = 0;
    }
    ASSERT_RETURN_NULL(parent);
    if (0 == (parent->num % 0x08))
    {
        // 每次一次性申请8块内存, 若第9个属性追加时还会触发再申请8块内存;
        int oldsize = (parent->num) * sizeof(asn1_value);
        int newsize = (0x08) * sizeof(asn1_value);
        parent->arr = (asn1_value*)realloc(parent->arr, oldsize + newsize);
        unsigned char* start = (unsigned char*)parent->arr;
        memset(start + oldsize, 0, newsize);
    }
    return &parent->arr[parent->num++];
}

int asn1_decode_value(OUT asn1_value* val, IN const unsigned char* input)
{
    ASSERT_RETURN_0(val);
    ASSERT_RETURN_0(input);

    int size = asn1_get_info(&val->tag, &val->len, &val->data, input);
    input += size;

    if ((0x30 == val->tag) || (0x31 == val->tag) || (val->tag & 0xA0))
    {
        int decode_size = 0;
        while (decode_size < val->len)
        {
            asn1_value* child = asn1_add_value(val);
            ASSERT_RETURN_0(child);

            int child_size = asn1_decode_value(child, input);
            ASSERT_RETURN_0(child_size > 0);

            decode_size += child_size;
            input += child_size;
        }
    }

    return size + val->len;
}

asn1_value* asn1_get_children(IN const asn1_value* val, IN const int index)
{
    ASSERT_RETURN_NULL(val);
    ASSERT_RETURN_NULL(index >= 0);
    ASSERT_RETURN_NULL(index < val->num);
    ASSERT_RETURN_NULL(val->arr);

    return &(val->arr[index]);
}

Boolean asn1_get_Boolean(OUT asn1_Boolean* interger, IN const asn1_value* val)
{
    ASSERT_RETURN_FALSE(interger);
    ASSERT_RETURN_FALSE(val);
    ASSERT_RETURN_FALSE(ASN1_TAG_Boolean == val->tag);
    ASSERT_RETURN_FALSE(1 == val->len);
    ASSERT_RETURN_FALSE(val->data);

    *interger = (*val->data) ? True : False;

    return True;
}

Boolean asn1_get_Interger(OUT asn1_Interger* interger, IN const asn1_value* val)
{
    ASSERT_RETURN_FALSE(interger);
    ASSERT_RETURN_FALSE(val);
    ASSERT_RETURN_FALSE(ASN1_TAG_Interger == val->tag);
    ASSERT_RETURN_FALSE(val->len <= 8);
    ASSERT_RETURN_FALSE(val->data);

    *interger = 0;
    int len = val->len;
    unsigned char* data = val->data;
    while (len-- > 0)
    {
        *interger = (*interger << 8) | *data++;
    }

    return True;
}

static Boolean asn1_get_string(OUT asn1_string* bitstring, IN const asn1_value* val)
{
    ASSERT_RETURN_FALSE(bitstring);
    ASSERT_RETURN_FALSE(val);

    bitstring->len = val->len;
    bitstring->data = val->data;

    return True;
}

Boolean asn1_get_BitString(OUT asn1_BitString* bitstring, IN const asn1_value* val)
{
    ASSERT_RETURN_FALSE(ASN1_TAG_BitString == val->tag);
    return asn1_get_string(bitstring, val);
}

Boolean asn1_get_OctetString(OUT asn1_OctetString* octetstring, IN const asn1_value* val)
{
    ASSERT_RETURN_FALSE(ASN1_TAG_OctetString == val->tag);
    return asn1_get_string(octetstring, val);
}

/* oid byte -> int */
unsigned char* ASN1_OID2Int(OUT int* val, IN unsigned char* input)
{
    ASSERT_RETURN_NULL(val);
    ASSERT_RETURN_NULL(input);

    *val = 0;
    while ((*input) & 0x80)
    {
        *val = ((*val) << 7) | ((*input++) & 0x7F);            // 取后7位 累加到val
    }
    *val = ((*val) << 7) | ((*input++) & 0x7F);

    return input;
}

Boolean asn1_get_ObjectIdentifier(OUT asn1_ObjectIdentifier* objectidentifier, IN const asn1_value* val)
{
    ASSERT_RETURN_FALSE(objectidentifier);
    ASSERT_RETURN_FALSE(val);
    ASSERT_RETURN_FALSE(val->data);

    int len = val->len;
    unsigned char* start = val->data;
    const unsigned char* end = start + len;

    int temp = 0;
    int offset = 0;
    int res = 0;
    start = ASN1_OID2Int(&temp, start);
    objectidentifier->data = (unsigned char*)malloc(32);
    /*printf("malloc %p \n", objectidentifier->data);*/
    memset(objectidentifier->data, 0, 32);
    res = sprintf((char*)(objectidentifier->data + offset), "%d.%d.", temp / 40, temp % 40);
    offset += res;

    while (start < end)
    {
        start = ASN1_OID2Int(&temp, start);
        res = sprintf((char*)(objectidentifier->data + offset), "%d.", temp);
        offset += res;
    }
    objectidentifier->data[offset - 1] = '\0'; // 把最后一个.抹掉
    objectidentifier->len = offset - 1;

    return True;
}

/* 调试输出 */
int asn1_value_print(IN asn1_value* val, int level)
{
    ASSERT_RETURN_NULL(val);
    int i = 0;
    for (i = 0; i < level; i++)
    {
        printf("  ");
    }
    printf("type:[%d] len[%d] \n", val->tag, val->len);

    int j = 0;
    for (j = 0; j < val->num; j++)
    {
        asn1_value_print(asn1_get_children(val, j), level + 1);
    }
}
View Code

调用

#include <stdio.h>
#include <string.h>
#include "base64.h"
#include "asn1.h"

int main()
{
    unsigned char strEncode64[8 * 1024] = "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";
    
    unsigned char strDecode64[8 * 1024] = {0};
    int iDecodeLen = 0;
    int iRes = base64_decode(strDecode64, &iDecodeLen, strEncode64, strlen((char*)strEncode64));

    asn1_value val;
    asn1_init_value(&val);

    iRes = asn1_decode_value(&val, strDecode64);
    asn1_value_print(&val, 0);

    return 0;
}

 

posted on 2022-07-18 18:59  仲达超  阅读(801)  评论(0编辑  收藏  举报

导航