借助openssl将数据转换为ASN1 der格式

本文是参照别的文章,再根据自己实践后整理的,若有不当之处,还请批评指正!

使用openssl将C结构体转换为ASN1 Der格式时,首先需要包含如下几个头文件:

#include <openssl/asn1.h>

#include <openssl/asn1t.h>

#include <openssl/ossl_typ.h>

然后,按如下三个步骤进行操作,通过示例程序进行介绍,假如想将结构体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 结构体本身数据 是要大几个字节的。

猜你喜欢

转载自blog.csdn.net/chunfangzhang/article/details/84667331