藉助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 結構體本身資料 是要大幾個位元組的。