半自动化创建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颁发证书给客户端

建议颁发的证书文件都放在统一的目录下,颁发的第一个证书是在serial01开始

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和申请证书的主要内容,如果未能解决你的问题,请参考以下文章

私有CA的创建和证书的申请

创建CA 和申请证书

http怎么做自动跳转https

创建私有CA并进行证书申请

Centos7.3创建CA和申请证书

Linux如何创建私有CA和申请证书