半自动化创建CA和申请证书
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了半自动化创建CA和申请证书相关的知识,希望对你有一定的参考价值。
1 概述
本文之所以称之为半自动化,是因为证书的申请并非日常工作,只是一段时间才需要申请,同时,在创建证书和办法证书的时候,有些参数需要根据用户的需求自己调整,如证书的有效时间,还有,是否给私钥加密等等,因为叫脚本设置为半自动化,手动输入一些参数,到达用户的需求。当然如果环境是固定,参数也是固定,有效时间固定,该脚本配合crontab也可以实现自动化申请和颁发等操作
CA中心又称CA机构,即证书授权中心(Certificate Authority ),或称证书授权机构。本文将介绍通过openssl这个工具如何创建根CA,子CA,证书申请,证书颁发 和吊销证书等操作进行介绍
2 概念
2.1 创建私有CA
openssl的配置文件:/etc/pki/tls/openssl.cnf.这个配置文件里的相关配置,如证书信息匹配策略,证书的相关文件保存路径和命名都在这里做规定,本文将在文末附属该配置文件部分重要参数的介绍
其中,证书信息匹配策略有三种:匹配、支持和可选
匹配指要求申请填写的信息跟CA设置信息必须一致,支持指必须填写这项申请信息,可选指可有可无
用户在自己机器生成证书请求文件后,将对应请求文件发给服务器,服务器收到请求文件后,确认无误,将对于进行签发,并把证书发给申请主机
2.2 证书申请步骤
证书的申请有如下四个步骤
a. 生成申请请求
由客户端自己创建,完成后将生成的文件发送到证书签发机构
b. RA核验,
RA(Registration Authority),数字证书注册审批机构。RA系统是CA的证书发放、管理的延伸。它负责证书申请者的信息录入、审核以及证书发放等工作(安全审计)。同时,对发放的证书完成相应的管理功能(安全管理)。
c. CA签署
核验通过后,在CA服务器生成证书
d. 获取证书
将创建完成的证书发给申请者
3. 实验步骤
3.1 创建根CA
3.1.1、创建所需要的文件
touch /etc/pki/CA/index.txt
#生成证书索引数据库文件
echo 01 >
/etc/pki/CA/serial
#指定第一个颁发证书的序列号
3.1.2 CA自签证书
要先有私钥,才能给自己颁发证书
生成私钥,文件名是固定的,而且目录也是当前固定的目录,因为在配置文件里指定了路径和名称
cd /etc/pki/CA/
执行以下这步后会在该目录下生成加密的文件
(umask 066; openssl genrsa-out /etc/pki/CA/private/cakey.pem -des 3 2048)
.生成自签名证书,给自己签名,-x509是关键字,表示要自己申请,而且给自己颁发证书
这里文件的路径都是有要求的,以下要输入密码
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -days 7300 -out /etc/pki/CA/cacert.pem
要输入密码,然后要提交信息
-new: 生成新证书签署请求
-x509: 专用于CA生成自签证书
-key: 生成请求时用到的私钥文件
-days n:证书的有效期限
-out /PATH/TO/SOMECERTFILE: 证书的保存路径
3.2 创建子CA
3.2.1 子CA上创建私钥和证书请求文件
方法和根CA基本一致
在 /etc/pki/CA下创建serial 和index.txt
以下加密des3,如果加密,每次办法都要输入密码
作为子CA,不能给自己颁发证书,要向根CA申请证书,不加x509选项
生成subca.csr文件,把这个文件复制到服务器根CA对应的目录/etc/kpi/CA/下
3.2.2 根CA上颁发证书给子CA
这里对根私钥加了口令,所有要先输入密码,才能输入信息
生成文件subca.crt,把这个文件拷贝到子CA上,注意,这个文件拷贝到子CA上的时候,要把名称改成
cacert.pem,才能作为服务器端的私钥给客户端来签名颁发
到这里服务器端根CA操作完成,此时子CA可以给其他的客户端颁发证书了
3.2.3 验证
找一台机器,向子CA申请证书
生成请求文件,这里输入的选项要和根CA的配置文件策略一致
完成后,将这个请求文件发送到子CA上
这个操作在3.3里讲到
3.2.4 子CA颁发证书给客户端
建议颁发的证书文件都放在统一的目录下,颁发的第一个证书是在serial从01开始
openssl ca -in rhel5.csr -out certs/rhel5.crt -days 300
出现如下报错,有的奇怪,都是henan,但是还是报错,因为这客户端版本5上的openssl版本和子CA上版本不一致,
导致不兼容。解决颁发是升级openssl的版本为同一版本
3.3颁发证书
3.3.1 在需要使用证书的主机生成证书请求
给web服务器生成私钥,test.key 这个名字可以自命名,但是后缀不能 该,2048是长度
(umask066; openssl genrsa-out /etc/pki/tls/private/test.key 2048)
生成证书申请文件,用私钥来生成请求文件,后缀一般建议为csr,和服务器生成基本一致,少了关键字-x509,表示不是自签名,而是申请证书
-days 365申请时间,这个时间是没有意义的,因为是由服务器端颁发的时候指定,客户端指定时间是没有意义的
openssl req -new -key /etc/pki/tls/private/test.key -days 365 -out /etc/pki/tls/test.csr
这里的请求文件名(key名)每一次是默认要不一样的,如果要运行,需要更改index.txt.attr里的yes改成no
这里私钥文件没有加密des,所以和服务器不一样,不需要回车后填密码,只需要回车后填入信息
国家,省,公司这三项是配置模板里规定match的,所以要和服务器端一样
3.3.2 发送请求文件给CA
将证书请求文件传输给CA,可以用scp拷贝到服务器端对应的路径
3.3.3CA签署证书,并将证书颁发给请求者
-days 365这里指定的时间是有效期,让客户端用多久的时间,有效的,不指定默认就是服务配置文件设定的时间
commonName = supplied这个字段是supplied,如果新的证书请求的信息的commonName和之前的请求信息一样,,那么当上一个请求信息生成的证书还没有被吊销的时候,新的证书将不再生成,生成0字节的文件
openssl ca -in /tmp/test.csr -out /etc/pki/CA/certs/test.crt -days 365
完成后把证书文件发回给客户端
3.4 吊销证书
当客户出现异常,服务器端可以吊销证书
3.4.1在客户端获取要吊销的证书的serial
openssl x509 -in /PATH/FROM/CERT_FILE [-noout|-serial|-subject]
3.4.2 在CA上吊销
根据客户提交的serial与subject信息,对比检验是
否与index.txt文件中的信息一致,吊销证书:
这一步是在CA服务上操作的,吊销后证书状态为R
openssl ca -revoke /etc/pki/CA/newcerts/SERIAL.pem
吊销后,要把这个信息发布出去。客户端才知道哪些证书被吊销
3.4.3 指定第一个吊销证书的编号
在服务器根CA上操作
crlnumber证书吊销列表编号,在index.txt这个文件里可以看到证书的状态
echo 01 > /etc/pki/CA/crlnumber
/etc/pki/CA/crlnumber里保存的数字表示
接下去要吊销的是第几个证书,如已经吊销了5个证书,则当前文件保存的就是06,表示接下去要吊销第6个证书
注意:第一次更新证书吊销列表前,才需要执行,如果之前已经吊销过证书,这个语句就不需要执行了
3.4.4 更新证书吊销列表
把这个文件发布到官方网站上,让所有使用者都知道证书被吊销了
openssl ca -gencrl -out /etc/pki/CA/crl/crl.pem
3.4.5查看crl文件
执行如下语句进行查看,不是必须的步骤
openssl crl -in /etc/pki/CA/crl/crl.pem -noout -text
4 半自动化脚本
以下的脚本,将实现以上5个步骤,为了方便演示,将操作写在同一脚本里。通过选项操作对应的操作。
用户只需要输入相关操作,就可以完成CA的搭建和证书申请,颁发,吊销等操作
脚本如下
#!/bin/bash # #****************************************************************************** #Author: Sunny #Date: 2017-09-09 #FileName: install_ca.sh #version: 1.0 #Your change info: #Description: For auto create CA,subCA,generate and revoke cert #Copyright(C): 2017 All rihts reserved #***************************************************************************** CApath=/etc/pki/CA certpath=/etc/pki/CA/certs tlspath=/etc/pki/tls tlsprivatepath=/etc/pki/tls/private caprivatepate=/etc/pki/CA/private #check certification info,run below cmd #openssl x509 -in cent7bbaa.crt -noout -text #check certification request infomation,run cmd as below #openssl req -noout -text -in aa.csr #check certification status,run cmd as below,01 is serial number #openssl ca -status 01 active_ip(){ actip=$(ip a| grep -E "[0-9]+\/"| cut -d / -f1|sed -nr ‘[email protected]*( [0-9]+\.[^0][0-9]*\.[0-9]+\.[0-9]+)@\[email protected]‘|cut -d " " -f2|head -1) } pri_key_name(){ echo "private key name should end with .key,such as clent.key" read -p "enter your private key name(default:client."$actip".key) " prikey if [ -z ${prikey:-} ];then prikey=client."$actip".key fi } cli_csr_name(){ echo "Cert request name should end with .crs,such as clent.csr" read -p "enter your cert request name(default:client."$actip".csr) " clicsr if [ -z ${clicsr:-} ];then clicsr=client."$actip".csr fi } key_length(){ echo "key length should be one of 1024,2048,4096" read -p "enter your private key length(default:2048): " length if [ -z ${length:-} ]; then length=2048 fi } root_pre(){ [ -e "$CApath"/index.txt ] || touch "$CApath"/index.txt [ -e "$CApath"/serial ] || echo 01 > "$CApath"/serial #create a server private key echo "unless you have modify ca private key name in /etc/pki/tls/openssl.cnf,only use default cakey.pem"read -p "enter your ca private key name accord to openssl.cnf (default:cakey.pem) " cakey if [ -z ${cakey:-} ];then cakey=cakey.pem fi key_length if [ -e "$caprivatepate"/"$cakey" ] ;then echo "The server already have private key,$cakey, under "$caprivatepate"/,please check" else umask 066; read -p "enter yes to encrypt private key,other enter will no enrypt: " yorn if [ "$yorn" = yes ];then read -p "enter encrypt key word(eg:-des3): " encry openssl genrsa -out "$caprivatepate"/"$cakey" "$encry" "$length" else openssl genrsa -out "$caprivatepate"/"$cakey" "$length" fi umask 022; fi } echo "Enter 1 : run at root CA server and rootca_sig_itself" echo "Enter 2 : run at sub_server,generate a private key and signature request file,and send request file to root CA " echo "Enter 3 : run at client host,generate certification requst file and send to server auto" echo "Enter 4 : run at server,generate certification and send to client auto" echo "Enter 5 : run at server,to revoke some certification" read -p "Please input your choice: " choice case $choice in 1) root_pre; #generate a signature certificate for itself,-x509 is key work,means it signature to itself echo "unless you have modify ca signature certificate name in /etc/pki/tls/openssl.cnf,only use default cacert.pem" read -p "enter your ca signature cer name accord to openssl.cnf (default:cacert.pem) " cacert if [ -z ${cacert:-} ];then cacert=cacert.pem fi if [ -e "$CApath"/"$cacert" ] ;then echo "The server already have signature certificate,"$cacert" under "$CApath",please check" else openssl req -new -x509 -key "$caprivatepate"/"$cakey" -days 7300 -out "$CApath"/"$cacert" fi ;; 2) root_pre; #generate a signature certificate request file and send to root CA read -p "enter your ca signature cer request file (default:subca.csr): " subcacert if [ -z ${subcacert:-} ];then subcacert=subca.csr fi if [ -e "$CApath"/"$subcacert" ] ;then echo "The sub ca already have signature certificate,"$subcacert"under "$CApath",please check" else openssl req -new -key "$caprivatepate"/"$cakey" -days 7300 -out "$CApath"/"$subcacert" fi #send request file to root CA read -p "which root CA would you send(default:192.168.32.61): " serip if [ -z ${serip:-} ];then serip=192.168.32.61 fi expect -c " spawn scp "$CApath"/"$subcacert" [email protected]"$serip":"$CApath"/certs/ expect { \"*assword\" {set timeout 500; send \"Pass1234\r\"; } \"yes/no\" { send \"yes\r\"; exp_continue; } } expect eof" ;; 3) echo "Please check whether you are in client" #client generate private key active_ip pri_key_name cli_csr_name key_length if [ -e "$tlsprivatepath"/"$prikey" ] ;then echo "The client already have private key "$prikey" under "$tlsprivatepat",please check" else umask 066; if [ "$yorn" = yes ];then read -p "enter encrypt key word(eg:-des3): " encry openssl genrsa -out "$tlsprivatepath"/"$prikey" "$encry" "$length" else openssl genrsa -out "$tlsprivatepath"/"$prikey" "$length" fi umask 022; fi #generate a signature certificate to root ca,without -x509. if [ -e "$tlspath"/"$clicsr" ] ;then echo "The client already have signature certificate request file,"$clicsr" under "$tlspath",please check" else openssl req -new -key "$tlsprivatepath"/"$prikey" -out "$tlspath"/"$clicsr" fi #send request file to CA read -p "which CA would you send(default:192.168.32.61): " serip if [ -z ${serip:-} ];then serip=192.168.32.61 fi expect -c " spawn scp "$tlspath"/"$clicsr" [email protected]"$serip":"$CApath"/certs/ expect { \"*assword\" {set timeout 500; send \"Pass1234\r\"; } \"yes/no\" { send \"yes\r\"; exp_continue; } } expect eof" ;; 4) read -p "enter which requst file in "$CApath"/certs you want want server to generate as certification(eg:cent7.csr): " clientrsq read -p "enter new client cetification name(eg:cent7.crt): " crtname [ -e "$CApath"/certs/"$crtname" ] && { echo $crtname exist,please check;exit 6; } read -p "enter many days would the cert be avlid(eg:365): " days if [ -e "$CApath"/certs/"$clientrsq" ];then #attention,no only $crtname be generated,but also serial.pem file will be generate under dir newcerts openssl ca -in "$CApath"/certs/"$clientrsq" -out "$CApath"/certs/"$crtname" -days "$days" else echo "$clientrsq does no exist in "$CApath"/certs,please check" fi read -p "which client would you send(eg:192.168.32.61): " clip expect -c " spawn scp "$CApath"/certs/"$crtname" [email protected]"$clip":"$tlspath" expect { \"*assword\" {set timeout 500; send \"Pass1234\r\"; } \"yes/no\" { send \"yes\r\"; exp_continue; } } expect eof" ;; 5) read -p "Please input the serial number you want to revoke(eg:03): " sernum echo "you can run cmd openssl x509 -in cent7bt.crt -noout -text to check the serial number,cent7bt.crt is the certification you want to revoke" openssl ca -revoke /etc/pki/CA/newcerts/"$sernum".pem crlnum=$(cat /etc/pki/CA/crlnumber) [ -z $crlnum ] && echo 01 > /etc/pki/CA/crlnumber; openssl ca -gencrl -out /etc/pki/CA/crl/crl.pem; #check the the crl list #openssl crl -in /etc/pki/CA/crl/crl.pem -noout -text ;; *) echo "your input is wrong,please check" ;; esac unset ip unset crtname unset CApath unset clinetsrq
5 /etc/pki/tls/openssl.cnf 讲解
本附录只针对一些重要字段用中文做了备注,内容如下
/etc/pki/tls/openssl.cnf CA的配置文件,这个文件文件很关键,配置和CA密切相关 [ CA_default ] 这里新创建的文件名必须一样,如果要改,就要跟defaults一样 dir = /etc/pki/CA # Where everything is kept,CA工作目录,CA信息保存的目录 # certs = $dir/certs # Where the issued certs are kept,定义一个变量 crl_dir = $dir/crl # Where the issued crl are kept,证书吊销列表 database = $dir/index.txt # database index file.这个是一个文件,保存证书数据库,如颁发了哪些证书,证书编号,证书状态等信息保存在这里,这个文件默认没有,要手工创建一个空文件,颁发证书的时候,会手动颁发,没有空文件的话,颁发的时候会报错 #unique_subject = no # Set to ‘no‘ to allow creation of # several ctificates with same subject. new_certs_dir = $dir/newcerts # default place for new certs.默认新证书的放置目录,这个文件是自动生成的,用数字编号 certificate = $dir/cacert.pem # The CA certificate,CA自己的证书,根CA自己给自己颁发,子CA上级颁发 serial = $dir/serial # The current serial number,要手动创建,当前系列号,是一个16进制数,实际意义是下一个证书的编号,默认是从00开始,可以自己指定开始的值,必须是16进制数 crlnumber = $dir/crlnumber # the current crl number,证书吊销编号,也是指下一个证书被吊销的编号,即下一个被吊销的证书的编号 # must be commented out to leave a V1 CRL crl = $dir/crl.pem # The current CRL private_key = $dir/private/cakey.pem# The private key。CA的私钥 RANDFILE = $dir/private/.rand # private random number file,随机数 x509_extensions = usr_cert # The extentions to add to the cert # Comment out the following two lines for the "traditional" # (and highly broken) format. name_opt = ca_default # Subject Name options,命名方式 cert_opt = ca_default # Certificate field options # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs # so this is commented out by default to leave a V1 CRL. # crlnumber must also be commented out to leave a V1 CRL. # crl_extensions = crl_ext default_days = 365 # how long to certify for,证书的有效期,可以指定 default_crl_days= 30 # how long before next CRL,CRL的有效期 default_md = default # use public key default MD preserve = no # keep passed DN ordering # A few difference way of specifying how similar the request should look # For type CA, the listed attributes must be the same, and the optional # and supplied fields are just that :-) policy = policy_match,策略,由下面来指定,表示客户要申请证书的时候,要求客户提供的信息 # For the CA policy [ policy_match ] 这个是系统默认的策略 countryName = match 国家,match是必须匹配,两边都是同样的信息,其他的可以不一样 stateOrProvinceName = match 省,match如果不一样,就会拒绝,不会颁发证书 organizationName = match 组织 organizationalUnitName = optional 部门 commonName = supplied 通用名,如网站服务器的域名,一般是严格匹配,也可以写成泛域名,申请费用比较贵 emailAddress = optional ,可选项,不强制要求一样 # For the ‘anything‘ policy # At this point in time, you must list all acceptable ‘object‘ # types. [ policy_anything ] 给外部使用,不用match选项,都不要求完全一样 countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 2048 default_md = sha1 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # The extentions to add to the self signed cert
6 总结
由于openssl这个命令很强大,有大量的参数,本文只是列出的参数是生成很颁发等必须用到的几个参数,如果需要有更多其他选项,用户可自行添加
本文出自 “自学linux” 博客,请务必保留此出处http://ghbsunny.blog.51cto.com/7759574/1964754
以上是关于半自动化创建CA和申请证书的主要内容,如果未能解决你的问题,请参考以下文章