本文是参照别的文章,再根据自己实践后整理的,若有不当之处,还请批评指正!
使用openssl将C结构体转换为ASN1 Der格式时,首先需要包含如下几个头文件:
#include
#include
#include
然后,按如下三个步骤进行操作,通过示例程序进行介绍,假如想将结构体ECCrefPublicKey 进行转换,该结构体定义如下:
typedef struct ECCrefPublicKey_st
{
unsigned char x[ECCref_MAX_LEN];
unsigned char y[ECCref_MAX_LEN];
} ECCrefPublicKey;
第一步:在头文件中定义如下结构体,并进行声明
//结构体定义(将其理解为ASN1格式下与ECCrefPublicKey相对应的结构,我们的目的就是将普通二进制格式下的ECCrefPublicKey转换为ASN1标准对应下的格式,有点类似于我们数学中学的一一映射的意思)
Typedef struct ASN_ECCPUBLICKEY_st
{
ASN1_OCTET_STRING *X;
ASN1_OCTET_STRING *Y;
} ASN_ECCPUBLICKEY;
//随后使用如下语句进行声明
DECLARE_ASN1_FUNCTIONS(ASN_ECCPUBLICKEY)
ASN_ECCPUBLICKEY 中 X Y分量对应于ECCrefPublicKey中两个分量,其类型对应于ASN1 下的类型,ASN1下的数据类型也有很多,根据实际要求进行定义。
第二步: 在实现文件.C文件中声明一些变量和结构体:
ASN1_SEQUENCE(ASN_ECCPUBLICKEY) = {
ASN1_SIMPLE(ASN_ECCPUBLICKEY, X, ASN1_OCTET_STRING),
ASN1_SIMPLE(ASN_ECCPUBLICKEY, Y, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(ASN_ECCPUBLICKEY);
其中每一项,对应于第一步中定义的ASN1结构体变量。
第三步:在实现文件.C文件中调用实现宏
IMPLEMENT_ASN1_FUNCTIONS(ASN_ECCPUBLICKEY)
第三步就上面一个语句,一般放在第二步的后面。此时,ASN1转换准备工作就执行完毕了,通过上面三个步骤,openssl就为其定义了如下几个函数:
d2i_ ASN_ECCPUBLICKEY( )、i2d_ASN_ECCPUBLICKEY()、ASN_ECCPUBLICKEY_new( )、ASN_ECCPUBLICKEY_free()
至此,就可以依据这四个函数来对C结构体进行转换了,借助于上面四个函数定义如下函数:
int i2d_ECC_PublicKey(const ECCrefPublicKey *cipher, unsigned char **out)
{
ASN_ECCPUBLICKEY *ec = NULL;
int len = 0;
ec = ASN_ECCPUBLICKEY_new();
if (ec == NULL) {
return 0;
}
do {
if (!ASN1_OCTET_STRING_set(ec->X, cipher->x, 32))
break;
if (!ASN1_OCTET_STRING_set(ec->Y, cipher->y, 32))
break;
/* i2d */
len = i2d_ASN_ECCPUBLICKEY(ec, out);
} while (0);
ASN_ECCPUBLICKEY_free(ec);
return len; //返回值时编码为ASN1后的 字节大小
}
int d2i_ECC_PublicKey(ECCrefPublicKey *ins, const unsigned char **ppin, long pplen)
{
ASN_ECCPUBLICKEY *ec = NULL;
/* DECODE */
ec = d2i_ASN_ECCPUBLICKEY(NULL, ppin, pplen);
if (ec == NULL) {
return 0;
}
/* check version ? */
do {
if (ec->X->length <= 0 || ec->Y->length <= 0)
break;
memcpy(ins->x, ec->X->data, ec->X->length);
memcpy(ins->y, ec->Y->data, ec->Y->length);
ASN_ECCPUBLICKEY_free(ec);
return 1;
} while(0);
ASN_ECCPUBLICKEY_free(ec);
return 1;
}
此后,我们直接调用i2d_ECC_PublicKey 和 d2i_ECC_PublicKey 两个函数,就可以实现C结构体到 Der格式之间的相互转换。(完)
补充:C结构体中各成员变量都是二进制数据,我们可以按 十六进制 方式打印显示,ASN1 Der格式是在C结构体数据本身基础上,添加了一些标记的结果。因此ASN1 Der编码的数据 比C 结构体本身数据 是要大几个字节的。