Openssl证书操作

来源:互联网 发布:海德曼数控车床编程 编辑:程序博客网 时间:2024/05/22 04:37

公司的那个虚拟VPN的项目摸索进行中,近期写完了几个小模块,遂想测试一下,结果网上找来的证书都是过期的,无奈只能自己动手做。研究了2天左右,总结了一下,现分享出来。

先概括一下将要讲述的内容:建立CA中心、自签名证书(根证书)、用户证书请求、签名颁发、证书吊销、证书验证。

实验环境就不说了。小case,大家自行安装。

建立工作目录:

$mkdir ~/cert$cd ~/cert$mkdir ca user

以上目录中,cert为我们实验的根目录,在cert下,有ca、user两个目录,前者作为CA中心(以后主要职责是建立、签名、颁发、吊销等操作)、后者作为一个普通用户(请求CA认证并生成数字证书)。

现在先建立CA:

$cd ca$mkdir private certs usrcerts crl conf$chmod g-rwx,o-rwx ~/cert/ca  #安全考虑,封死所有其他用户(当然, 对root无效)

其中private用来存放私钥;certs用于存放CA的根证书;newcerts用于存放CA签发过的用户证书;crl存放吊销列表;conf用来存放一些简化参数用的配置文件、索引序列号。

$touch index.txt$echo "01" > serial

拷贝模板配置文件到conf目录、修改之:

$cp /usr/share/ssl-cert/ssleay.cnf conf$mv conf/ssleay.cnf conf/cainfo.cnf$vi conf/cainfo.cnf

输入以下内容(里面有一些信息科根据实际情况修改):

[ req ]default_keyfile = private/ca.pemdefault_md = md5prompt = nodistinguished_name = ca_distinguished_namex509_extensions = ca_extensions[ ca_distinguished_name ]organizationName = EtarayorganizationalUnitName  = Dev-DepartmentcommonName = Development-DepartmentemailAddress = likai503819723@gmail.com[ ca_extensions ]basicConstraints = CA:true

保存退出(别跟我说vi你不会用)。

配置参数详细含义见: http://linux.chinaunix.net/techdoc/net/2007/06/18/960441.shtml

接下来制作私钥:

$ openssl genrsa -des3 -out private/ca.pem 1024

期间需要我们两次输入密码,假设我们输入:888888

解释:openssl指进入openssl环境;genrea是环境中的一个命令即generate RSA(生成RSA私钥);-des3指使用des3对称加密算法加密我们生成的私钥,我们设置888888密码即des3的密钥(除了-des3还可指定其他对称算法,也可以不使用-des3加密私钥文件,但只有傻瓜才这么做);-out即指定输出目录及文件名;1024指私钥长度1024bit。

下面开始建立自签名证书(即根证书),但是,需要先使用req填一张表(比如到银行办张卡,需要登记一些信息什么的):

$openssl req -new -x509 -days 7300 -key private/ca.pem -out certs/ca.crt

解释:req即openssl环境下的一个命令,意即request请求;-new即新请求;-x509即输出形式是X509结构体而不是证书请求应答信息。-days即证书有效天数,此处设置为20年(7300=365*20,天呐);-key 使用私钥文件,这里使用我们刚刚生成的那个;-out即输出目录及文件名。 PS:输入$openssl req -help所有参数一目了然。

以上的命令将会提示你首先输入私钥文件ca.pem的密码(就是888888),因为程序需要先解码它,再提取私钥对新证书签名。
然后输入国家名、单位名等等,这样比较麻烦,还记得我们的那个conf/cainfo.cnf吗?将那里面的信息导入,一键搞定:

$openssl req -new -x509 -days 7300 -key private/ca.pem -out certs/ca.crt -config conf/cainfo.cnf
当然,如果你就是想手工输入新的CA单位信息,那可以使用第一条命令而不用cnf文件。
此时查看certs目录下就有了ca.crt证书。
下面再建立一个配置文件,用于CA日常操作:
$vi conf/hdlcert.cnf
内容:
[ ca ]default_ca     = cadir            = /home/XXXXXXXX/cert/ca      # top dir,修改为你的实际目录。database       = $dir/index.txt          # index file.new_certs_dir  = $dir/usrcerts           # user certs dircertificate    = $dir/certs/ca.crt         # The CA certserial         = $dir/serial             # serial no fileprivate_key    = $dir/private/ca.pem  # CA private keyRANDFILE       = $dir/private/.rand      # random number filedefault_days   = 365                     # how long to certify fordefault_crl_days= 30                     # how long before next CRLdefault_md     = md5                     # message digest method to useunique_subject = no                      # Set to 'no' to allow creation of                                         # several ctificates with same subject.policy         = policy_any              # default policy[ policy_any ]countryName             = CNstateOrProvinceName     = ZheJianglocalityName            = HangZhouorganizationName        = EtarayorganizationalUnitName  = Dev-SectioncommonName              = kyleemailAddress            = likai503819723@gmail.com

导出环境变量,以使程序使用自定义的配置文件:

$export OPENSSL_CONF="/home/kyle/cert/ca/conf/hdlcert.cnf"
注意,这样导入环境变量只对本次登录有效,重启后失效,可考虑写入到配置文件如.bashrc
至此,CA中心建成。
问:如果不导入环境变量会怎样?答:如果不导入,那么在使用OpenSSL命令行执的时候,如果需要用到配置参数,则将默认使用/etc/ssl/openssl.cnf这个文件。这里面的参数有些并不是我们想要的,故需要重新指配。

------------------俺是华丽滴分割线-------------------------

下面开始使用CA颁发客户证书:
进入到user目录下,并生成自己的私钥(此处插曲一下,客户的私钥只能自己拥有,谁也不能说,即使是给自己颁发证书的CA也不能告诉它!就像我们的银行卡密码,连银行也不能告诉。):
$cd ~/cert/user$chmod g-rwx,o-rwx ~/cert/user  #同ca目录一样,封死所有其他用户$mkdir conf csr private$openssl genrsa -des3 -out private/client.pem 1024
过程中输入密码,我们输入111111,。有了私钥,我们再拿私钥生成一个X509格式的csr请求文件(Certificate Signing Request,csr),将它发送给CA,CA签名后,生成crt证书。

下面在conf目录下建立一个cnf文件,用于导入用户的信息:
$vi conf/usrinfo.cnf
内容如下:
[ req ]default_keyfile = private/client.pem  #注意,倘若你要其他pem,那就在命令行加上-key filename 选项指定私钥路径,届时会覆盖此项。default_md = md5prompt = nodistinguished_name = usr_distinguished_name[ usr_distinguished_name ]organizationName = EtarayorganizationalUnitName  = Dev-SectioncommonName = KyleemailAddress = likai503819723@gmail.com

生成请求文件:
$openssl req -new -key private/client.pem -out csr/client.csr -config conf/usrinfo.cnf
提示输入我们上面设置的密码,111111.
完成后csr目录多了个client.csr.将其发送给CA中心(此处直接mv过去即可):

$mv csr/client.csr ../ca/usrcerts/
CA中心进行签发(先cd到ca目录):

$ openssl x509 -req -in usrcerts/client.csr -out usrcerts/client.crt -CA certs/ca.crt -days 365 -CAserial serial -CAkey private/ca.pem
解释:-req表示请求;-in/-out输入输出文件;-CA证书,必须是PEM格式编码(即不能是DER编码);-days 证书有效天数;-CAserial CA的序列号;-CAkeyyy CA的私钥。
需要输入密码,即888888。
此时签发完成,将usrcerts/client.crt发送给用户即可。

-----------------------俺是华丽滴分割线-------------------------
下面讲讲CA吊销证书。不知道”吊销”二字含义的同学请谷歌或百度。
吊销已经签发的证书,需要使用ca命令的-revoke,假如我们需要吊销刚刚建立的证书:
$ ca -revoke usrcerts/client.crt -keyfile private/ca.pem -cert certs/ca.crt 

然后生成吊销列表文件:

openssl ca -gencrl  -out crl/crl.crl -keyfile pivate/ca.pem -cert certs/ca.crt

这样crl/ca.crl吊销列表文件就生成了。同时index.txt也被更新了:

$cat index.txtR       080313185625Z   070314192229Z   02      unknown /C=CN/ST=ZheJiang/L=HangZhou/O=Etaray/OU=Dev-Section/CN=kyle/emailAddress=18955914664@163.com
以后,吊销列表就可以发送给用户,用户就可以验证证书是否被吊销。

最后,验证一下用户证书:
$ openssl verify -CAfile certs/ca.crt usrcerts/client.crt
出现OK即表示验证成功。

最后再附上一个验证证书的小程序,C语言版的:

#include <stdio.h>#include <string.h>#include <dlfcn.h>#include <openssl/x509.h>#include <openssl/pem.h>void tX509_Verify(){int rv;X509_STORE_CTX *ctx = NULL;//证书存储区句柄X509 *usrCert = NULL;//X509证书结构体,保存用户证书//X509 *caCert = NULL;//X509证书结构体,保存CA证书X509 *rootCert = NULL;//X509证书结构体,保存根证书X509_CRL *Crl = NULL;//X509_CRL结构体,保存CRLSTACK_OF(X509) *caCertStack = NULL;X509_STORE *rootCertStore = NULL;//证书存储区//int j = 0;FILE *fp;//读取根证书fp=fopen("root.crt","rb");if(fp==NULL){printf("open root.crt file err\n");return ;}rootCert = PEM_read_X509(fp, NULL, NULL, NULL);fclose(fp);//读取CRL文件fp=fopen("crl.crl","rb");if(fp==NULL){printf("open crl.crl file err\n");return ;}Crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);fclose(fp);//读取待验证的用户证书fp=fopen("client.crt","rb");if(fp==NULL){printf("open client.crt file err\n");return ;}usrCert = PEM_read_X509(fp, NULL, NULL, NULL);fclose(fp);fp = NULL;//新建X509证书存储区rootCertStore = X509_STORE_new();//添加根证书到证书存储区X509_STORE_add_cert(rootCertStore,rootCert);//设置检查CRL标志位,如果设置此标志位,则检查CRL,否则不检查CRL。X509_STORE_set_flags(rootCertStore,X509_V_FLAG_CRL_CHECK);//添加CRL到证书存储区X509_STORE_add_crl(rootCertStore,Crl);//新建证书存储区句柄ctx = X509_STORE_CTX_new();//初始化根证书存储区、用户证书rv = X509_STORE_CTX_init(ctx,rootCertStore,usrCert,caCertStack);if(rv != 1){printf("X509_STORE_CTX_init err\n");X509_free(usrCert);X509_free(rootCert);X509_STORE_CTX_cleanup(ctx);X509_STORE_CTX_free(ctx);X509_STORE_free(rootCertStore);return;}//验证用户证书1rv = X509_verify_cert(ctx);if(rv != 1){printf("verify client.crt err.error= %d,info:%s\n",ctx->error,X509_verify_cert_error_string(ctx->error));}else{printf("verify client.crt OK\n");}//释放内存X509_free(usrCert);X509_free(rootCert);X509_STORE_CTX_cleanup(ctx);X509_STORE_CTX_free(ctx);X509_STORE_free(rootCertStore);return;}void tGetX509Info(){<span style="white-space:pre"></span>X509 *x509Cert = NULL;<span style="white-space:pre"></span>//X509证书结构体<span style="white-space:pre"></span>unsigned char *pTmp = NULL;<span style="white-space:pre"></span>X509_NAME *issuer = NULL;<span style="white-space:pre"></span>//X509_NAME结构体,保存证书颁发者信息<span style="white-space:pre"></span>X509_NAME *subject = NULL;<span style="white-space:pre"></span>//X509_NAME结构体,保存证书拥有者信息<span style="white-space:pre"></span>int i;<span style="white-space:pre"></span>int entriesNum;<span style="white-space:pre"></span>X509_NAME_ENTRY *name_entry;<span style="white-space:pre"></span>//<span style="white-space:pre"></span>ASN1_INTEGER *Serial = NULL;<span style="white-space:pre"></span>//保存证书序列号<span style="white-space:pre"></span>long Nid;<span style="white-space:pre"></span>ASN1_TIME *time;<span style="white-space:pre"></span>//保存证书有效期时间<span style="white-space:pre"></span>EVP_PKEY *pubKey;<span style="white-space:pre"></span>//保存证书公钥<span style="white-space:pre"></span>long Version;<span style="white-space:pre"></span>//保存证书版本<span style="white-space:pre"></span>FILE *fp;<span style="white-space:pre"></span>unsigned char derpubkey[1024];<span style="white-space:pre"></span>int derpubkeyLen;<span style="white-space:pre"></span>unsigned char msginfo[1024];<span style="white-space:pre"></span>int msginfoLen;<span style="white-space:pre"></span>unsigned short *pUtf8 = NULL;<span style="white-space:pre"></span>int nUtf8;<span style="white-space:pre"></span>int rv = 0;<span style="white-space:pre"></span>//打开用户证书文件<span style="white-space:pre"></span>fp=fopen("client.crt","rb");<span style="white-space:pre"></span>if(fp==NULL)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>printf("open client.crt file err\n");<span style="white-space:pre"></span>return ;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>//用户证书转化成X509结构体<span style="white-space:pre"></span>x509Cert = PEM_read_X509(fp, NULL, NULL, NULL);<span style="white-space:pre"></span>fclose(fp);<span style="white-space:pre"></span>fp = NULL;<span style="white-space:pre"></span>//获取证书版本<span style="white-space:pre"></span>Version = X509_get_version(x509Cert);<span style="white-space:pre"></span>printf("X509 Version:%ld\n",Version);<span style="white-space:pre"></span>//获取证书序列号<span style="white-space:pre"></span>Serial = X509_get_serialNumber(x509Cert);<span style="white-space:pre"></span>//打印证书序列号<span style="white-space:pre"></span>printf("serialNumber is: \n");<span style="white-space:pre"></span>for(i = 0; i < Serial->length; i++)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>printf("%02x", Serial->data[i]);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>printf("\n");<span style="white-space:pre"></span><span style="white-space:pre"></span>//获取证书颁发者信息,X509_NAME结构体保存了多项信息,包括国家、组织、部门、通用名、mail等。<span style="white-space:pre"></span>issuer = X509_get_issuer_name(x509Cert);<span style="white-space:pre"></span>//获取X509_NAME条目个数<span style="white-space:pre"></span>entriesNum = sk_X509_NAME_ENTRY_num(issuer->entries);<span style="white-space:pre"></span>//循环读取各条目信息<span style="white-space:pre"></span>for(i=0;i<entriesNum;i++)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>//获取第I个条目值<span style="white-space:pre"></span>name_entry = sk_X509_NAME_ENTRY_value(issuer->entries,i);<span style="white-space:pre"></span>//获取对象ID<span style="white-space:pre"></span>Nid = OBJ_obj2nid(name_entry->object);<span style="white-space:pre"></span>//判断条目编码的类型<span style="white-space:pre"></span>if(name_entry->value->type==V_ASN1_UTF8STRING)//把UTF8编码数据转化成可见字符<span style="white-space:pre"></span>{<span style="white-space:pre"></span><span style="white-space:pre"></span>nUtf8 = 2*name_entry->value->length;<span style="white-space:pre"></span>pUtf8 = malloc(nUtf8);<span style="white-space:pre"></span>memset(pUtf8,0,nUtf8);<span style="white-space:pre"></span>/*<span style="white-space:pre"></span>rv = MultiByteToWideChar(<span style="white-space:pre"></span>CP_UTF8,<span style="white-space:pre"></span>0, <span style="white-space:pre"></span>(char*)name_entry->value->data, <span style="white-space:pre"></span>name_entry->value->length, <span style="white-space:pre"></span>pUtf8, <span style="white-space:pre"></span>nUtf8);<span style="white-space:pre"></span>rv = WideCharToMultiByte(<span style="white-space:pre"></span>CP_ACP, <span style="white-space:pre"></span>0, <span style="white-space:pre"></span>pUtf8, <span style="white-space:pre"></span>rv, <span style="white-space:pre"></span>(char*)msginfo, <span style="white-space:pre"></span>nUtf8, <span style="white-space:pre"></span>NULL, <span style="white-space:pre"></span>NULL);*/<span style="white-space:pre"></span>free(pUtf8);<span style="white-space:pre"></span>pUtf8 = NULL;<span style="white-space:pre"></span>msginfoLen = rv;<span style="white-space:pre"></span>msginfo[msginfoLen]='\0';<span style="white-space:pre"></span>}<span style="white-space:pre"></span>else<span style="white-space:pre"></span>{<span style="white-space:pre"></span>msginfoLen=name_entry->value->length;<span style="white-space:pre"></span>memcpy(msginfo,name_entry->value->data,msginfoLen);<span style="white-space:pre"></span>msginfo[msginfoLen]='\0';<span style="white-space:pre"></span>}<span style="white-space:pre"></span>//根据NID打印出信息<span style="white-space:pre"></span>switch(Nid) <span style="white-space:pre"></span>{<span style="white-space:pre"></span>case NID_countryName://国家<span style="white-space:pre"></span>printf("issuer 's countryName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_stateOrProvinceName://省<span style="white-space:pre"></span>printf("issuer 's ProvinceName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_localityName://地区<span style="white-space:pre"></span>printf("issuer 's localityName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_organizationName://组织<span style="white-space:pre"></span>printf("issuer 's organizationName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_organizationalUnitName://单位<span style="white-space:pre"></span>printf("issuer 's organizationalUnitName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_commonName://通用名<span style="white-space:pre"></span>printf("issuer 's commonName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_pkcs9_emailAddress://Mail<span style="white-space:pre"></span>printf("issuer 's emailAddress:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>}//end switch<span style="white-space:pre"></span>}<span style="white-space:pre"></span>//获取证书主题信息<span style="white-space:pre"></span>subject = X509_get_subject_name(x509Cert);<span style="white-space:pre"></span>//获得证书主题信息条目个数<span style="white-space:pre"></span>entriesNum = sk_X509_NAME_ENTRY_num(subject->entries);<span style="white-space:pre"></span>//循环读取个条目信息<span style="white-space:pre"></span>for(i=0;i<entriesNum;i++)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>//获取第I个条目值<span style="white-space:pre"></span>name_entry = sk_X509_NAME_ENTRY_value(subject->entries,i);<span style="white-space:pre"></span>Nid = OBJ_obj2nid(name_entry->object);<span style="white-space:pre"></span>//判断条目编码的类型<span style="white-space:pre"></span>if(name_entry->value->type==V_ASN1_UTF8STRING)//把UTF8编码数据转化成可见字符<span style="white-space:pre"></span>{<span style="white-space:pre"></span>nUtf8 = 2*name_entry->value->length;<span style="white-space:pre"></span>pUtf8 = malloc(nUtf8);<span style="white-space:pre"></span>memset(pUtf8,0,nUtf8);<span style="white-space:pre"></span><span style="white-space:pre"></span>/*rv = MultiByteToWideChar(<span style="white-space:pre"></span>CP_UTF8,<span style="white-space:pre"></span>0, <span style="white-space:pre"></span>(char*)name_entry->value->data, <span style="white-space:pre"></span>name_entry->value->length, <span style="white-space:pre"></span>pUtf8, <span style="white-space:pre"></span>nUtf8);<span style="white-space:pre"></span>rv = WideCharToMultiByte(<span style="white-space:pre"></span>CP_ACP, <span style="white-space:pre"></span>0, <span style="white-space:pre"></span>pUtf8, <span style="white-space:pre"></span>rv, <span style="white-space:pre"></span>(char*)msginfo, <span style="white-space:pre"></span>nUtf8, <span style="white-space:pre"></span>NULL, <span style="white-space:pre"></span>NULL);*/<span style="white-space:pre"></span>free(pUtf8);<span style="white-space:pre"></span>pUtf8 = NULL;<span style="white-space:pre"></span>msginfoLen = rv;<span style="white-space:pre"></span>msginfo[msginfoLen]='\0';<span style="white-space:pre"></span>}<span style="white-space:pre"></span>else<span style="white-space:pre"></span>{<span style="white-space:pre"></span>msginfoLen=name_entry->value->length;<span style="white-space:pre"></span>memcpy(msginfo,name_entry->value->data,msginfoLen);<span style="white-space:pre"></span>msginfo[msginfoLen]='\0';<span style="white-space:pre"></span>}<span style="white-space:pre"></span>switch(Nid) <span style="white-space:pre"></span>{<span style="white-space:pre"></span>case NID_countryName://国家<span style="white-space:pre"></span>printf("subject 's countryName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_stateOrProvinceName://省<span style="white-space:pre"></span>printf("subject 's ProvinceName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span><span style="white-space:pre"></span>case NID_localityName://地区<span style="white-space:pre"></span>printf("subject 's localityName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_organizationName://组织<span style="white-space:pre"></span>printf("subject 's organizationName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_organizationalUnitName://单位<span style="white-space:pre"></span>printf("subject 's organizationalUnitName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_commonName://通用名<span style="white-space:pre"></span>printf("subject 's commonName:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>case NID_pkcs9_emailAddress://Mail<span style="white-space:pre"></span>printf("subject 's emailAddress:%s\n",msginfo);<span style="white-space:pre"></span>break;<span style="white-space:pre"></span>}//end switch<span style="white-space:pre"></span>}<span style="white-space:pre"></span>//获取证书生效日期<span style="white-space:pre"></span>time = X509_get_notBefore(x509Cert);<span style="white-space:pre"></span>printf("Cert notBefore:%s\n",time->data);<span style="white-space:pre"></span>//获取证书过期日期<span style="white-space:pre"></span>time = X509_get_notAfter(x509Cert);<span style="white-space:pre"></span>printf("Cert notAfter:%s\n",time->data);<span style="white-space:pre"></span>//获取证书公钥<span style="white-space:pre"></span>pubKey = X509_get_pubkey(x509Cert);<span style="white-space:pre"></span>pTmp=derpubkey;<span style="white-space:pre"></span>//把证书公钥专为为DER编码的数据<span style="white-space:pre"></span>derpubkeyLen=i2d_PublicKey(pubKey,&pTmp);<span style="white-space:pre"></span>printf("PublicKey is: \n");<span style="white-space:pre"></span>for(i = 0; i < derpubkeyLen; i++)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>printf("%02x", derpubkey[i]);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>printf("\n");<span style="white-space:pre"></span>X509_free(x509Cert);<span style="white-space:pre"></span>return;}int main(){ OpenSSL_add_all_algorithms();tX509_Verify();tGetX509Info();return 0;}

索性把makefile也给贴上吧(注意其中头文件、库文件的路径需要根据实际情况修改):

OBJS = main.oCC = gccINCLUDES = -I./include -I/usr/local/ssl/includeLIBS =  -L/usr/local/ssl/lib -lssl -lcrypto -ldlCFLAGS =  -g -Wall -pthreadp12test: $(OBJS)$(CC) $^ -o $@ $(LIBS)%.o:%.c$(CC) -c $< $(INCLUDES) $(CFLAGS).PHONY:cleanclean:-rm -f *.o p12test

在运行程序时,证书文件(根证书root.crt、用户证书client.crt、吊销列表crl.crl)的路径不要放错。

0 0