26.openssl编程——X509数字证书

26.1 X509数字证书
数字证书是将用户(或其他实体)身份与公钥绑定的信息载体。一个合法的数字证书不仅要符合X509格式规范,还必须有CA的签名。用户不仅有自己的数字证书,还必须有对应的私钥。
X509V3数字证书主要包含的内容有:
a.证书版本
b.证书序列号
c.签名算法
d.颁发者信息
e.有效时间
f.持有者信息
g.公钥信息
h.颁发者信息
i.公钥信息
j.颁发者ID
k.扩展项
26.2 openssl实现
openssl实现了标准x509v3数字证书,其源码在x509v3中。其中x509目录实现了数字证书以及证书申请相关的各种函数,包括X509和X509_REQ结构的设置、读取打印和比较。数字证书的验证、摘要;各种公钥导入导出等功能。x509v3目录主要实现了数字证书扩展项相关的函数。
26.3 X509数据结构
struct x509_cinf_st {
ASN1_INTEGER *version; 版本
ASN1_INTEGER serialNumber; 序列号
X509_ALGOR signature; 签名算法
X509_NAME *issuer; 颁发者
X509_VAL validity; 有效时间
X509_NAME *subject; 持有者
X509_PUBKEY *key; 公钥
ASN1_BIT_STRING *issuerUID; 颁发者唯一标识
ASN1_BIT_STRING *subjectUID; 持有者唯一标识
STACK_OF(X509_EXTENSION) *extensions; 扩展项
ASN1_ENCODING enc;
}
struct x509_st {
X509_CINF cert_info; 证书主体信息
X509_ALGOR sig_alg; 签名算法
ASN1_BIT_STRING signature; 签名值
X509_SIG_INFO siginf;
CRYPTO_REF_COUNT references; 引用次数,被引用一次则加一
CRYPTO_EX_DATA ex_data; 扩展数据结构,用于存放用户自定义的信息
long ex_pathlen; 证书路径长度,对应扩展项为NID_basic_constraints
long ex_pcpathlen;
uint32_t ex_flags; 通过与计算存放各种标志
uint32_t ex_kusage; 密钥用法
uint32_t ex_xkusage; 扩展密钥用法
uint32_t ex_nscert; 证书类型
ASN1_OCTET_STRING *skid; 主体密钥标识
AUTHORITY_KEYID *akid; 颁发者密钥标识
X509_POLICY_CACHE *policy_cache; 各种策略缓存
STACK_OF(DIST_POINT) *ctldp;
STACK_OF(GENERAL_NAME) *altname;
NAME_CONSTRAINTS *nc;
#ifndef OPENSSL_NO_RFC377G
STACK_OF(IPAddressFamily) *rfc3779_addr;
struct ASIdentifiers_st *rfc3779_asid;
#endif
unsigned cahr sha1_hash[SHA_DIGEST_LENGTH]; 存放证书的sha1摘要值
X509_CERT_AUX *aux;辅助信息
CRYPTO_RWLOCK *lock;
}
26.4 X509_TRUST与X509_CERT_AUX
a. typedef struct x509_trust_st {
int trust;
int flags;
int (*check_trust) (struct x509_trust_st *, X509 *, int);
char *name;
int arg1;
void *arg2;
} X509_TRUST;
static X509_TRUST trstandard[] = {
{X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
{X509_TRUST_SSL_CLIENT, 0, trust_loidany, "SSL CLient", NID_client_aut, NULL},
{X509_TRUST_SSL_SERVER, 0, trust_loidany, "SSL Server", NID_server_auth, NULL},
{X509_TRUST_EMAIL, 0, trust_loidany, "S/MIME email", NID_email_protect, NULL},
{X509_TRUST_OBJECT_SIGN, 0, trust_loidany, "Object Signer", NID_code_sign, NULL},
{X509_TRUST_OCSP_SIGN, 0, trust_loid, "OCSP responder", NID_OCSP_sign, NULL},
{X509_TRUST_OCSP_REQUEST, 0, trust_loid, "OCSP request", NID_ad_OCSP, NULL},
{X509_TRUST_TSA, 0, trust_loidany, "TSA server", NID_time_stamp, NULL}
}
X509_CERT_AUX
typedef struct X509_cert_aux_st
{
STACK_OF(ASN1_OBJECT) *trust;
STACK_OF(ASN1_OBJECT) *reject;
ASN1_UTF8STRING *alias;
ASN1_OCTET_STRING *keyid;
STACK_OF(X509_ALGOR) *other;
}
验证证书时,如果要验证某个ASN1_OBJCT是否受信任,查找到相应的check_trust,进行计算。如果对应项在标准表trstandard中,除了X509_TRUST_COMPAT(检查证书用途)都会调用obj_trus函数
26.5 X509_PURPOSE
typedef struct x509_purpose_st {
int purpose;
int trust;
int flags;
int (*check_purpose) (const struct x509_purpose_st *, const X509*, int);
char *name;
char *sname;
void *usr_data;
}
purpsoe为证书用途ID,check_purpose为检查证书用途函数
#define X509_PURPOSE_SSL_CLIENT 1
#define X509_PURPOSE_SSL_SERVER 2
#define X509_PURPOSE_SSL_NS_SSL_SERVER 3
#define X509_PURPOSE_SMIME_SIGN 4
#define X509_PURPOSE_SMIME_ENCRYPT 5
#define X509_PURPOSE_CRL_SIGN 6
#define X509_PURPOSE_ANY 7
#define X509_PURPOSE_OCASP_HELPER 8
#define X509_PURPOSE_TIMESTAMP_SIGN 9
维护了两个表
static X509_PURPOSE xstandard[] = {
{X509_PURPSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0
check_purpose_ssl_client, ""SSL client}, "sslclient", NULL},
{X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
check_purpose_ssl_server, "SSL server", "sslserver", NULL},
{X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
check_purpose_ns_ssl_server, "Netscape SSL server", "nesslever", NULL},
{X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,"S/MIME sgning", "smimesign", NULL},
{X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
{X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
"CRL signing", "crlsign", NULL},
{X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any PUrpose", "any", NULL},
{X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helpoer, "OCSP helper", "ocsphelper", NULL},
{X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, "TIme Stamp signing", "timestampsign", NULL},
};
26.6 主要函数
函数
功能
X509_STORE_add_cert
将证书添加到X509_STORE中
X509_STORE_add_crl
将crt添加到X509_STORE中
X509_STORE_set_flags
将flags赋值给ctx里面的flags,表明验证证书时需要验证哪些项
X509_TRUST_set_default
设置默认的X509_TRUST检查函数
X509_verify
验证证书的签名
X509_verify_cert
验证证书,用法可参考apps/verify.c
X509_verify_cert_error_string
根据错误号,获取错误信息
X509_add1_ext_i2d
根据具体的扩展项数据结构添加一个扩展项
X509_add_ext
X509_EXTENSION堆栈中,在制定位置添加一项
X509_ALGOR_dup
算法拷贝
X509_alias_get0
X509_alias_set1
获取/设置别名
X509_asn1_meth
获取X509的ASN1_METHOD,包括new\free\i2d和d2i函数
X509_certificate_type
获取证书和公钥类型
X509_check_private_key
检查私钥与证书中的公钥是否匹配,匹配返回1
X509_cmp
证书比较
X509_cmp_current_time
将s与当前时间进行比较,返回值小于0则s遭遇当前时间,
大于0则晚于当前时间
X509_cmp_time
如果ctm时间在cmp_time之后,则返回值大于0.
X509_delete_ext
删除扩展项堆栈中指定位置的扩展项
X509_digest
根据制定的摘要算法对X509结构做摘要
X509_dup
拷贝函数
X509_find_by_issuer_and_serial
根据颁发这X509_NAME名称和证书序列号,
在X509堆栈中查找对应的证书并返回
X509_find_by_subject
从证书堆栈中根据持有者名字查询证书,并返回
X509_get0_pubkey_bitstr
获取X509结构中的DER编码的公钥信息
X509_load_cert_crl_file
加载证书和crl,也能给予验证证书
X509_PURPOSE_get0
根据X509_PURPOSE的位置获取对应的X509_PURPOSE
X509_PURPOSE_get0_name
获取X509_PURPOSE的名字
X509_PURPOSE_get0_sname
获取X509_PURPOSE的别名
X509_PURPOSE_get_by_id
根据证书用途ID获取X509_PURPOSE在当前数组(xstandard)
或堆栈中的位置,如果没有返回-1
X509_PURPOSE_get_by_sname
根据别名获取对应的X509_PURPOSE的数组或堆栈中的位置
X509_PURPOSE_get_count
获取所有的X509_PURPOSE个数,包括标准和用户动态添加的
X509_PURPOSE_get_id
获取X509_PURPOSE的ID
X509_PURPOSE_set
检查是否有purpose标识X509_purpose,并将purpose值写入p
X509v3_add_ext
添加扩展项,堆栈操作,
将ex表示的扩展项根据loc指定的位置插入到X509_EXTENSION堆栈中
X509v3_delete_ext
堆栈操作,去除制定位置的扩展项
X509V3_EXT_print
本函数用于打印单个扩展项,out为BIO类型的输出对象
ext为扩展项,flag表明不支持扩展项的处理方式,indent表明输出时第一列的位置
X509V3_extensions_print
本函数将堆栈中的所有扩展项打印
X509v3_get_ext_by_critical
获取扩展项在堆栈中的位置,crit表明扩展项是否关键
X509v3_get_ext_by_NID
获取扩展项在其堆栈中的位置,
此函数根据扩展项标识nid以及堆栈搜索的其实进行搜索
X509v3_get_ext_by_OBJ
获取扩展项在堆栈中的位置,crit表面扩展项是否关键
X509v3_get_ext
获取扩展项,loc为扩展项在堆栈x中的位置,如果不成功,返回NULL
X509v3_get_ext_count
获取扩展项的个数,此函数调用堆栈操作
sk_X509_EXTENSION_num
X509_get_section
获取配置信息,section为配置信息中的段信息。
X509V3_get_string
根据段和属性获取值
X509V3_get_value_bool
判断配置信息的布尔值,如果value表示的值为true,TRUE
X509V3_get_value_int
将value中的值转换为ASN1_INTEGER类型,
结果存放在**aint中,函数调用成功返回1,否则返回0
X509V3_parse_list
分析配置信息的一行数据,返回结果
26.7 证书验证项
a. 数字证书验证中,主要考察的项有
*有效期,看证书是否已经失效
*签名,用颁发者的公钥来验证签名
*证书用途
*名字比较,证书中的颁发者信息应与颁发者证书的持有者信息一致;扩展项约束。
b.Openssl中的证书验证
Openssl中的证书验证比较复杂,实现源码X509/X509_vfy.c中,主要有两个函数:X509_verify_cert和internal_verify.X509_verify_cert主要讲所有的证书信息进行排序,构造出一个有序的证书链,然后interanl_verify函数来验证证书。internal_verify是openssl提供的一个内置的验证证书链的函数。如果用户通过X509_STRORE_set_verify_func函数设置了X509_STORE_CTX的verify函数,将调用用户是实现的verify函数而不会调用internal_veriify。如何用openssl函数验证证书,用户可以参考apps/verify.c
posted @ 2018-01-25 17:06  艾小小雨  阅读(1640)  评论(0编辑  收藏  举报