第二十六章 X509数字证书 / 26.3 X509数据结构

该结构定义在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_nscertNetscape证书类型,对应扩展项为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_constraintsNID_certificate_policiesNID_policy_mappingsNID_inhibit_any_policy(见policy_cache_newpolicy_cache_set函数);

              sha1_hash:存放证书的sha1摘要值;

              aux:辅助信息;

              上述两个结构的DER编解码接口由宏在crypto/asn1/x_x509.c中实现,包括各自的newfreei2dd2i函数。

       DER解码编程示例如下:

       #include <openssl/x509.h>

       int    main()

       {

              X509                    *x;

              FILE                     *fp;

              unsigned charbuf[5000],*p;

              int                         len,ret;

              BIO                      *b;

      

              /* cert.cerDER编码的数字证书

用户如果是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:6c:00:aa:00:64:8a:11:cf:b8:d4:aa:5c:35:f4

        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:8a:a4:6f:ed:d6:e7:d9:66:0f:55:

                    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:5f:42:b6:9d:

                    23:36:0b:de:54:0f:cd:bd:1f:99:2a:10:58:11:cb:

                    40:cb:b5:a7:41

                Exponent: 65537 (0x10001)

        X509v3 extensions:

            commonName:

                .GFor Testing Purposes Only Sample Software Publishing Credentials Agency

            2.5.29.1:

                0>.....-...O..a!..dc..0.1.0...U....Root Agency...7l...d......\5.

    Signature Algorithm: md5WithRSAEncryption

        2d:2e:3e:7b:89:42:89:3f:a8:21:17:fa:f0:f5:c3:95:db:62:

        69:5b:c9:dc:c1:b3:fa:f0:c4:6f:6f:64:9a:bd:e7:1b:25:68:

        72:83:67:bd:56:b0:8d:01:bd:2a:f7:cc:4b:bd:87:a5:ba:87:

        20:4c:42:11:41:ad:10:17:3b:8c

       上述示例解码DER编码的数字证书,X509_print用于打印数字证书信息。

        如果需要解码PEM格式的证书,如下例:

        #include <openssl/x509.h>

              #include <openssl/pem.h>

              int    main()

              {

                     X509                    *x;

                     BIO                      *b;

             

                     /* cert.cerPEM格式的数字证书 */

                     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数据结构。