半自动化创建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; opensslgenrsa-out /etc/pki/tls/private/test.key2048)

生成证书申请文件,用私钥来生成请求文件,后缀一般建议为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  's@.*( [0-9]+\.[^0][0-9]*\.[0-9]+\.[0-9]+)@\1@p'|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"  root@"$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" root@"$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"  root@"$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这个命令很强大,有大量的参数,本文只是列出的参数是生成很颁发等必须用到的几个参数,如果需要有更多其他选项,用户可自行添加

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • CA和证书安全协议(SSL/TLS)OpenSSH 一、CA和证书 (一) PKI(Public Key Infr...
    哈喽别样阅读 1,381评论 0 0
  • 1.PKI: Public Key Infrastructure 签证机构:CA(Certificate Auth...
    尛尛大尹阅读 886评论 0 0
  • 年过花甲心不花 柴米油盐操持家 闲来常学刘玲醉 卧起搔首对晚霞 莫道君王御黔首 刹那...
    狼的传人说事阅读 173评论 0 0
  • 雨天可以做许多美妙的事情,看看电影、长长的午休、看看小说、喝茶聊天、雨中漫步……当然,画禅绕画也是不错的选择。 我...
    繁花坞阅读 695评论 14 14
  • 诗意的栖居 是自然赋予过客的芬芳水土 土地亲亲 闻不够的淳朴浓郁 碧蓝的天 跳进碧蓝的海里嬉戏 银铃般的笑声 飘荡...
    抱一阅读 133评论 0 1