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
实现文件
#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); } }
调用
#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; }