使用 OpenSSL 对 Octet String 类型数据进行 ASN.1 编码和解码

mac2024-08-22  61

        在 ASN.1 编码规则中,对于 Octet String 类型数据编码的方式是比较简单的,编码结果由三部分级联组成,如下图:

        其中标志位取值为0x4,负载部分的值就是原始的 Octet String 数据。         调用 OpenSSL 对 Octet String 类型数据进行 ASN.1 编码和解码,应使用 i2d_ASN1_OCTET_STRING( ) 及 d2i_ASN1_OCTET_STRING( ) 函数。函数 i2d_ASN1_OCTET_STRING( ) 的第一个输入参数的类型是指向指针的指针,即指针的地址,在函数内部的执行过程中,如果传入的第二个参数不是空指针,此时将执行实际的 ASN.1 编码操作,会修改输入的第一个指针参数的指向,即让输入的指针指向另一个地址,因此通常要使用一个临时变量指针,将这个临时指针的地址作为第一个输入参数输入值,这一点是需要特别注意的。对于 d2i_ASN1_OCTET_STRING( ) 函数,它的第二个参数是一个指针的地址,也会在执行解码时修改这个指针的指向,因此也要将一个临时指针的地址传入。具体的编码和解码过程可以看下面的示例程序:

/************************************************** * File name: octet_string_enc_and_dec.c * Author: HAN Wei * Author's blog: http://blog.csdn.net/henter/ * Date: Oct. 30th, 2019 * Description: demonstrate how to implement ASN.1 encode and decode on octet string data with OpenSSL **************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/asn1t.h> int main() { unsigned char sample_string[] = {0xE5, 0x02, 0x7C, 0xEF, 0xFF, 0x6d, 0x1A, 0xF9}; ASN1_OCTET_STRING my_asn1_octet_string, *test_asn1_octet_string; int encode_len, ret; unsigned char *p1, *p2; int sample_string_len, i; ASN1_OCTET_STRING *decode_result_pointer; unsigned char *decode_result; unsigned char *p3; sample_string_len = (int)sizeof(sample_string); printf("Sample octect string:\n"); for (i = 0; i < sample_string_len; i++) { printf("0x%x ", sample_string[i]); } printf("\n"); test_asn1_octet_string = &(my_asn1_octet_string); test_asn1_octet_string->length = sample_string_len; test_asn1_octet_string->data = sample_string; encode_len = i2d_ASN1_OCTET_STRING(test_asn1_octet_string, NULL); if ( encode_len < 0) { printf("Compute ASN.1 encode length failed!\n"); return (-1); } printf("ASN.1 encode length is %d bytes.\n", encode_len); if ( !(p1 = (unsigned char *)malloc(encode_len)) ) { printf("Memory allocation failed!\n"); return (-1); } p2 = p1; printf("Before ASN.1 encoding the pointer p2 points to the address: 0x%x\n", p2); ret = i2d_ASN1_OCTET_STRING(test_asn1_octet_string, &p2); if (ret < 0) { printf("ASN.1 encode failed!\n"); free(p1); return (-1); } printf("After ASN.1 encoding the pointer p2 points to the address: 0x%x\n", p2); printf("ASN.1 encode:\n"); for (i = 0; i < encode_len; i++) { printf("0x%x ", p1[i]); } printf("\n\n"); p3 = p1; decode_result_pointer = NULL; printf("Before ASN.1 decoding the pointer p3 points to the address: 0x%x\n", p3); if ( !(d2i_ASN1_OCTET_STRING(&decode_result_pointer, &p3, encode_len)) ) { printf("ASN.1 decode failed!\n"); free(p1); return (-1); } printf("After ASN.1 decoding the pointer p3 points to the address: 0x%x\n", p3); printf("Decoding result:\n"); printf(" length: 0x%x\n",decode_result_pointer->length); printf(" type: 0x%x\n",decode_result_pointer->type); printf(" flags: 0x%x\n",decode_result_pointer->flags); if ( !(decode_result = (unsigned char *)malloc(decode_result_pointer->length)) ) { printf("Memory allocation failed!\n"); ASN1_OCTET_STRING_free(decode_result_pointer); free(p1); return (-1); } if (decode_result_pointer->length != sample_string_len) { printf("Decode result length is wrong!\n"); free(decode_result); ASN1_OCTET_STRING_free(decode_result_pointer); free(p1); return (-1); } memcpy(decode_result, decode_result_pointer->data,decode_result_pointer->length); printf("Decoded octet string:\n"); for (i = 0; i < decode_result_pointer->length; i++) { printf("0x%x ", decode_result[i]); } printf("\n"); free(decode_result); ASN1_OCTET_STRING_free(decode_result_pointer); free(p1); return 0; }

        这个示例程序在编译和链接时,不管使用 OpenSSL 1.0.2d还是使用 OpenSSL 1.1.1,都能够通过,运行结果如下图:

最新回复(0)