该结构定义在crypto/x509.h中,如下:
typedef 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; /* 扩展项 */
} X509_CINF;
本结构是数字证书的信息主体;
struct x509_st
{
X509_CINF *cert_info;
X509_ALGOR *sig_alg;
ASN1_BIT_STRING *signature;
int valid;
int references;
char *name;
CRYPTO_EX_DATA ex_data;
long ex_pathlen;
long ex_pcpathlen;
unsigned long ex_flags;
unsigned long ex_kusage;
unsigned long ex_xkusage;
unsigned long ex_nscert;
ASN1_OCTET_STRING *skid;
struct AUTHORITY_KEYID_st *akid;
X509_POLICY_CACHE *policy_cache;
#ifndef OPENSSL_NO_SHA
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
#endif
X509_CERT_AUX *aux;
};
该结构表示了一个完整的数字证书。各项意义如下:
cert_info:证书主体信息;
sig_alg:签名算法;
signature:签名值,存放CA对该证书采用sig_alg算法签名的结果;
valid:是否是合法证书,1为合法,0为未知;
references:引用次数,被引用一次则加一;
name:证书持有者信息,内容形式为/C=CN/O=ourinfo……,该内容在调用d2i_X509的过程中,通过回调函数x509_cb(crypto/asn1/x_x509.c)调用X509_NAME_oneline来设置;
ex_data:扩展数据结构,用于存放用户自定义的信息;
扩展项信息,用于证书验证。下面的扩展项信息由crypto/x509v3/v3_purp.c中的x509v3_cache_extensions函数设置:
ex_pathlen:证书路径长度,对应扩展项为NID_basic_constraints;
ex_flags:通过“与”计算存放各种标记;
ex_kusage:密钥用法,对应扩展项为NID_key_usage;
ex_xkusage:扩展密钥用法,对应扩展项为NID_ext_key_usage;
ex_nscert:Netscape证书类型,对应扩展项为NID_netscape_cert_type;
skid:主体密钥标识,对应扩展项为NID_subject_key_identifier;
akid:颁发者密钥标识,对应扩展项为NID_authority_key_identifier;
policy_cache:各种策略缓存,crypto/x509v3/pcy_cache.c中由函数policy_cache_create设置,对应的策略为NID_policy_constraints、NID_certificate_policies、NID_policy_mappings和NID_inhibit_any_policy(见policy_cache_new和policy_cache_set函数);
sha1_hash:存放证书的sha1摘要值;
aux:辅助信息;
上述两个结构的DER编解码接口由宏在crypto/asn1/x_x509.c中实现,包括各自的new、free、i2d和d2i函数。
DER解码编程示例如下:
#include <openssl/x509.h>
int main()
{
X509 *x;
FILE *fp;
unsigned charbuf[5000],*p;
int len,ret;
BIO *b;
/* cert.cer为DER编码的数字证书
用户如果是windows系统,可以从IE中导出一个x509v3的数字证书作为解析目标
*/
fp=fopen("cert.cer","rb");
if(!fp) return -1;
len=fread(buf,1,5000,fp);
fclose(fp);
p=buf;
x=X509_new();
d2i_X509(&x,(const unsigned char **)&p,len);
b=BIO_new(BIO_s_file());
BIO_set_fp(b,stdout,BIO_NOCLOSE);
ret=X509_print(b,x);
BIO_free(b);
X509_free(x);
return 0;
}
程序输出:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
06:37:
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=Root Agency
Validity
Not Before: May 28 22:02:59 1996 GMT
Not After : Dec 31 23:59:59 2039 GMT
Subject: CN=Root Agency
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (512 bit)
Modulus (512 bit):
00:81:55:22:b9:
bc:d7:cd:d5:bc:4e:40:02:21:a2:b1:f7:87:30:85:
5e:d2:f2:44:b9:dc:9b:75:b6:fb:46:
23:36:0b:de:54:
40:cb:b5:a7:41
Exponent: 65537 (0x10001)
X509v3 extensions:
commonName:
.GFor Testing Purposes Only Sample Software Publishing Credentials Agency
0>.....-...O..a!..dc..
Signature Algorithm: md5WithRSAEncryption
2d:2e:3e:7b:89:42:89:
69:5b:c9:dc:c1:b3:fa:f0:c4:
72:83:67:bd:56:b0:8d:01:bd:
20:
上述示例解码DER编码的数字证书,X509_print用于打印数字证书信息。
如果需要解码PEM格式的证书,如下例:
#include <openssl/x509.h>
#include <openssl/pem.h>
int main()
{
X509 *x;
BIO *b;
/* cert.cer为PEM格式的数字证书 */
b=BIO_new_file("b64cert.cer","r");
x=PEM_read_bio_X509(b,NULL,NULL,NULL);
BIO_free(b);
X509_free(x);
return 0;
}
上例得到X509数据结构。