24.openssl编程——通用数据结构
24.1 通用数据结构
本文中数据结构主要指的是证书相关各个数据结构。他们主要用在数字证书申请、数字证书和CRL中。
*X509_ALGOR
X509算法
*X509_VAL
X509有效时间
*X509_PUBKEY
X509公钥
*X509_SIG
X509摘要或者签名值
*X509_NAME_ENTRY
X509中的一项名臣
*X509_NAME
X509名称集合
*X509_EXTENSION
X509扩展项
*X509_ATTRIBUTE
X509属性
*GENRAL_NAME
通用名称
通过openssl提供的ASN1库,这些数据结构都是可以进行DER编解码的。用户主要需要了解他们各项意义、对他们的编解码以及他们的set和get操作。
24.2 X509_ALOGOR
该数据结构用来表示算法,他定义在crypto/x509/x509.h
struct X509_algor_st
{
ASN1_OBJECT *algorithm;
ASN1_TYPE *parameter;
}
包含两项:
algorithm:ASN1_OBJECT类型,表明了是何种算法
parameter:ASN1_TYPE类型,代表该算法需要的参数。
该结构的DER编解码接口crypto/asn1/x_algor.c中由ASN1宏来实现,其中parameter是可选的。该结构相关的函数为new(生成数据结构)\free(释放数据结构)\i2d(将他转换为DER编码)\d2i(由DER编码转换为该结构)和dup(拷贝)
24.3 X509_VAL
该数据结构用来表示有效时间,定义在crypto/x509/x509.h
typedef struct X509_val_st
{
ASN1_TIME *notBefore;
ASN1_TIME *notAfter;
} X509_VAL;
包含两项
notBefore:生效日期
notAfter:失效日期
24.4 X509_SIG
该结构用来存放摘要或者签名值,定义crypto/x509/x509.h
typedef struct X509_sig_st
{
X509_ALGOR *algor;
ASN1_OCTET_STRING *digest;
} X509_SIG;
其中algor为算法,digest用于存放摘要或者签名值。对数据进行签名时,要先对数据摘要,摘要的结果要通过本结构进行DER编码,然后才能用私钥进行计算,此时digest中存放的就是摘要值。
24.5 X509_NAME_ENTRY
typedef struct X509_name_entry_st
{
ASN1_OBJECT *object;
ASN1_STRING *value;
int set;
int size;
} X509_NAME_ENTRY;
每个X509_NAME_ENTRY对应于一个证书中C\OU和O等实体名称,其中object表明了实体的类型是C还是OU等;value表明了改实体的内容,这两项用于DER编解码。该结构的DER编解码在crtypto/asn1/x_name.c中实现,包括new\free\i2d\d2i和dup函数。
24.6 X509_NAME
该结构是一个名称集合,在crypto/x509/x509.h
struct X509_name_st
{
STACK_OF(X509_NAME_ENTRTY) *entries;
int modified;
#ifndef OPENSSL_NO_BUFFER
BUF_MEM *bytes;
#else
char *bytes;
#endif
unsinged long hash;
}
a. int X509_NAME_add_entry(X509_NAME *name, X509_ENTRY *ne, int loc, int set)
将一个X509_NAME_ENTRY放入X509_NAME的堆栈中,在堆栈中的位置由loc制定。
b.int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, unsigned char *bytes, int len, int loc, int set)
根据nid在X509_NAME的X509_NAME_ENTRY堆栈中添加一项;
bytes为要添加项的值
type指明了types的ASN1类型
loc为堆栈中的位置
根据nid能偶获取ASN1_OBEJCT(OBJ_nid2obj函数)
c.X509_NAME_add_entry_by_OBJ
与b类似,知识要添加的项由ASN1_OBJECT来表示
d.X509_NAME_add_entry_by_txt
与b类似,只是要添加的项由字符串来表示,根据txt能获取ASN1_OBJECT
e.X509_NAME_ENTRY X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne,int nid, int type, unsigned char *bytes, int len )
根据nid来生成一个X509_NAME_ENTRY,bytes为要添加项的值,type指明了types的ASN1类型
f.X509_NAME_ENTRY_create_by_OBJ
生成项由ASN1_OBJECT来表示
g.X509_NAME_ENTRY_create_by_txt
生成的项有字符串表示
h.int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, cahr *buf, int len)
根据NID来获取值,结果存放在buf中
i.X509_NAME_get_text_by_OBJ
根据ASN1_OBJECT来获取值
j.int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos)
根据ASN1_OBJECT获取NAME_ENTRY在堆栈中的位置
k.X509_NAME_get_index_by_NID
根据NID获取X509_NAME_ENTRY在堆栈中的位置
l.X509_NAME_cmp
名字比较
m.X509_NAME_delete_entry
从堆栈中删除一个指定位置的X509_NAME_ENTRY,并将他返回。
n.X509_NAME_digest
根据指定的算法,对X509_NAME坐摘要计算
o.X509_NAME_dup
名字拷贝
p.X509_NAME_entry_count
获取X509_NAME的X509_NAME_ENTRY堆栈中元素个数
q.X509_NAME_ENTRY_dup
X509_NAME_ENTRY拷贝
r.X509_NAME_ENTRY_get/set_data
获取/设置一项名称的值;set函数还需要指明值的ASN1类型。
s.X509_NAME_ENTRY_get_entry
根据制定堆栈位置获取一个X509_NAME_ENTRY;
t.X509_NAME_hash
摘要计算,该结果是对MD5的结果处理后的值
将a表示的名字变成:/OU=z/CN=形式放在buf中,返回buf首地址。
u.X509_NAME_print/X509_NAME_print_ex
打印X509_NAME到bio中
v.X509_NAME_print_ex_fp
打印X509_NAME到FILE中
w.int X509_NAME_set(X509_NAME**xn, X509_NAME *name)
通过dup函数,设置*xn的为name.
24.7 X509_ENTENSION
本结构用于存放各种扩展项信息
a.结构定义
数据证书扩展项,定义在crypto/x509/x509.h中
typedef struct X509_extension_st
{
ASN1_OBJECT *object;
ASN1_BOOLEAN cirtical; 关键扩展项
ASN1_OCTET_STRING value; DER编码的具体扩展项的值
}
b. 通过X509V3_EXT_METHOD进行DER编解码
openssl通过X509V3_EXT_METHOD来实现对扩展项的编解码。
struct v3_ext_method
{
int ext_nid;
int ext_flags;
ASN1_ITEM_EXP *it;
X509V3_EXT_NEW ext_new;
X509V3_EXT_FREE ext_free;
X509V3_EXT_D2I d2i;
X509V3_EXT_I2D i2d;
X509V3_EXT_I2S i2s;
X509V3_EXT_S2I s2i;
X509V3_EXT_I2V i2v;
X509V3_EXT_V2I v2i;
X509V3_EXT_I2R i2r;
X509V3_EXT_R2I r2i;
void *usr_data;
}
该结构以ext_nid表示是何种扩展项,以it\d2i和i2d函数来指明来他的DER编解码函数。
从X509_EXTENSION中提取具体扩展项的数据结构可以采用如下函数
void *X509V3_EXT_d2i(X509_EXTENSION *ext)
该函数首先根据X509_EXTENSION来获取是那种扩展项,并查找X509V3_EXT_METHOD表,然后根据对应的d2i函数解码X509_extension->value中的DER编码数据,生成具体的扩展项数据结构并返回。
上述两个函数是具体扩展项和X509_EXTENSION相互转化最基本的函数,很多函数都基于他们。
#define X509V3_ADD_DEFAULT 0L
#define X509V3_ADD_APPEND 1L
#define X509V3_ADD_REPLACE 2L
#define X509V3_ADD_REPLACE_EXISTING 3L
#define X509V3_KEEP_EXISTING 4L
#define X509V3_ADD_DELETE 5L
#define X509V3_ADD_SILENT 0X10
24.8 X509_ATTRIBUTE
typedef struct x509_attributes_st
{
ASN1_OBJECT *object;
STACK_OF(ASN1_TYPE) *set;
}
主要函数:
a.int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr)
获取属性中ASN1_TYPE的个数
b.X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
生成一个属性。id用来生成ASN1_OBJECT,指明是哪种属性,atrtype为ASN1类型,value为值,用来设置set堆栈
c.X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **atr, const ASN1_OBJECT *obj, int atrytpe, const void *data, int len)
生成一个属性,obj指明了属性类型,atrtype为ASN1类型,data和len指明了需要设置的值。
d.X509_ATTRIBUTE_create_by_NID
同上,属性类型有nid指定
e.X509_ATTRIBUTE_create_by_txt
属性类型有ASN1_OBJECT的名字指定
f.X509_ATTRIBUTE_dup
拷贝函数
g. ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
获取属性中由堆栈位置idx指定的ASN1_TYPE, 如果属性不是set集合则返回value,single.
h.void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx)
由idx_he ASN1类型atrtype来获取value.ptr.
i.X509_ATTRIBUTE_get0_object
获取属性类型信息
j.X509_ATTRIBUTE_set1_data
设置属性信息
k.X509_ATTRIBUTE_set1_object
设置属性类型
l.STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTTRIBUTE) **x, X509_ATTRIBUTE *attr)
堆栈中添加一个属性,返回属性最站;如果*x为NULL, 则声称一个新的堆栈
m. X509at_add1_attr_by_OBJ
属性类型由ASN1_OBJECT指定。
n.X509at_add1_attr_by_txt
属性类型由属性名指定。
24.9 GENERAL_NAME
本结构用来表示通用名称x509v3.h中
typedef struct GENERAL_NAME_st {
#define GEN_OTHERNAME 0
#define GEN_EMAIL 1
#define GEN_DNS 2
#define GEN_X400 3
#define GEN_DIRNAME 4
#define GEN_EDIPRART 5
#define GEN_URI 6
#define GEN_IPADD 7
#define GEN_RID 8
int type;
union {
char *ptr;
OTHERNAME *otherName;
ASN1_IA5STRING *rfc822Name;
ASN1_IA5STRING *dNSName;
ASN1_TYPE *x400Address;
X509_NAME *directoryName;
EDIPARTYNAME *ediPartyName;
ASN1_IA5STRING *uniformResourceIdentifier;
ASN1_OCTET_STRING *iPAddress;
ASN1_OBJECT *registeredID;
ASN1_OCTET_STRING *ip;
X509_NAME *dirn;
ASN1_IA5STRING *ia5;
ASN1_OBJECT *rid;
ASN1_TYPE *other;
} d;
} GENERAL_NAME;
GENERAL_NAME可以包含各种各样的名称。type用来表示该结构采用了0~8分别对应otherName\rfc822Name、dNSName、x4000Address、directoryName\ediPartyName、uniformResourceIdentifier\iPAddress和registeredID.ptr用来存放通用的各种名称的地址。当type为某一个类型时,数据存放在d中对应的想。比如,当type为GEN_DIRNAME,数据存放在directoryName中。openssl中最常用的是X509_NAME.