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

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

使用 OpenSSL 对 Octet String 类型数据进行 ASN.1 编码和解码_第1张图片
        其中标志位取值为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 
#include 
#include 
#include 
 
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,都能够通过,运行结果如下图:

使用 OpenSSL 对 Octet String 类型数据进行 ASN.1 编码和解码_第2张图片

你可能感兴趣的:(OpenSSL)