背景
最近接到一个任务:由于我们的产品涉及使用数字证书进行签名、签章,如果需要使得签名签章暗具有法律效力,就必须使用权威CA中心颁发的数字证书,就需要小钱钱;但是对于测试来说,就可以适当减少小钱钱的使用;于是,可以考虑自建证书服务器,自己颁发证书,然后就使用自建证书服务器的颁发的证书测试就好了!
为了完成这个目的,第一步就是搭建证书服务器,于是我选了台linux服务器进行配置。
关于centos linux服务器系统配置证书服务器的资料网上有很多,过程中也踩了很多坑。不能说网上资料不对,只能说对自己不适用,嘿嘿嘿嘿 。 针对这个任务的完成过程以及中间涉及的知识点以及注意事项,我将行程一个系列来介绍。
本文是配置证书服务器的介绍。
一:安装openssl工具
rpm -qa openssl
yum install -y openssl
如上图所示,通过yum install -y openssl 安装openssl工具。安装好了openssl工具之后,默认安装目录为:/etc/pki/目录,
其默认配置文件目录为: /etc/pki/tls/openssl.cnf。该文件主要设置了证书请求、签名、crl相关的配置。主要相关的伪命令为ca和req。后将出一个openssl.cnf的详细介绍。
1.1openssl.cnf文件简介
该配置文件主要的作用如下:
1.1.1配置默认路径
配置默认路径:包括默认的CA路径dir、证书路径certs、crl路径crl_dir、根证书路径certificate、serial文件路径serial、私钥路径private_key等。生成根证书的私钥、证书时可以根据此配置文件里的设置设定文件名,也可以根据自己的需要自行设置文件名,然后再对此配置文件进行修改,将对应的文件名信息改正确。
一般需要设置的就是:
1)dir = /etc/pki/CA 设定这个路径 为home路径,所有ca相关的证书都在这个文件夹里
2)certificate = $dir/XXXX 设定根证书文件路径 ,这是自建证书服务器时需要去生成的。
3)serial = $dir/serial 这个 就建议就用serial做文件名,即需要在这个路径下生成一个名为serial的文件,并且需要向这个文件中添加初始值
4)private_key = $dir/private/XXXX # The private key 设定根证书对应的私钥文件路径
#################################################################### [ ca ] default_ca = CA_default # The default ca section #################################################################### [ CA_default ] dir = /etc/pki/CA # Where everything is kept 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 serial = $dir/serial # The current serial number 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 RANDFILE = $dir/private/.rand # private random number file |
1.1.2规定签发的证书的用途
如规定证书中的密钥用途:
这个证书用途的体现在:当使用证书浏览器查看时看到的密钥用法,如通过浏览器---internet选项---内容---证书---详细信息中显示的:
证书的用途一般分为两种:加密证书与签名证书,如常规的用于https验证的就只需要加密作用就行;,本次中需要的是签名证书,对于签名证书来说,其用途必须包含:Digital Signature。
这个需要在配置文件中开启,默认是不开放注释的状态。
要将其开放出来:
# This is typical in keyUsage for a client certificate. keyUsage = nonRepudiation, digitalSignature, keyEncipherment |
1.1.3规定证书信息的匹配情况
具体体现在证书生成证书请求文件时设定的要与根证书设定的一样,如果设定不一样,在做证书签名时就会报错,提示对应设定不匹配。
如:以下配置就要求 countryName、stateOrProvinceName、organizationName三个都是一样的。
# 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 stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional |
二:生成根证书
生成证书的步骤是:生成私钥文件---》生成证书请求文件---》生成公钥证书文件并进行签名。
生成证书的过程中会涉及多个文件,如:私钥文件、证书请求文件、公钥证书文件等,非常容易搞混淆,一定要区分清楚,建议就从文件名、后缀加以区分,否则就真的非常容易踩坑。如私钥就用xxxKey.pem;证书请求文件:xxxreq.pem、公钥证书文件:xxxCert.crt。一定要搞清楚自己的文件到底是哪种类型的!网上的资料很多就是,一下是这个后缀一下又是那个后缀,会搞懵逼的。
2.1生成根证书的私钥
openssl genrsa 命令是会用来生成 RSA 私有秘钥,不会生成公钥,因为公钥提取自私钥。生成私钥时是可以指定私钥长度和密码保护。如果需要查看公钥或生成公钥,可以使用 openssl rsa 命令。
openssl genrsa [-out filename] [-passout arg] [-aes128] [-aes192] [-aes256] [-camellia128] [-camellia192] [-camellia256] [-des]
可以通过openssl genrsa ?命令查看命令具体参数与用法:
[root@ecs-be9a CA]#openssl genrsa ?
usage: genrsa [args] [numbits]-des encrypt the generated key with DES in cbc mode-des3 encrypt the generated key with DES in ede cbc mode (168 bit key)-idea encrypt the generated key with IDEA in cbc mode-seedencrypt PEM output with cbc seed-aes128, -aes192, -aes256encrypt PEM output with cbc aes-camellia128, -camellia192, -camellia256encrypt PEM output with cbc camellia-out file output the key to 'file-passout arg output file pass phrase source-f4 use F4 (0x10001) for the E value-3 use 3 for the E value-engine e use engine e, possibly a hardware device.-rand file:file:...load the file (or the files in the directory) intothe random number generator
[root@ecs-be9a CA]#
openssl genrsa -out /etc/pki/CA/private/cakey.pem 2048 生成私钥,私钥中含有公钥,如果需要公钥,需要单独提取公钥 。
如果在openssl genrsa 命令中指定加密算法如 -des3 ,则会提示输入私钥保护密码,那么下次使用这个私钥文件的时候就会提示输入私钥密码,如命令:openssl genrsa -des3 -out test1.key 2048执行效果如下图所示:
2.2生成根证书的证书请求文件
2.2.1准备
在生成证书请求文件之前,需要形成记录数据的文件index.txt以及最初始的自签名证书的序列号可serial文件:
touch index.txt #生成数据记录文件index.txt
向serial中写入证书初始序列号,这个serial文件路径就按照openssl.cnf配置文件中的路径生成就可以。网上很多是向serial中写入01,像这样:
但是,实际上,这个序列号最终是显示到自签名的根证书的序列号里的,像这样:
并且对于x509证书来说,序列号应该是一个32位的类似uuid的标志证书序列号的,因此,我个人不建议直接向serial中写01,就随便一个32位的如:
a87a2d6dec4d07bd9095c9b2ee73b2ea
9579518878956341ccc51615197eb0f3
51b55180d6da29cdbaddf60d9430230a
5ce48cc7f764ad17aa6fe2a1ffab06d5
dd7b4730fa89a66b8edd977415a8b688
1ce7727ba8fb7be4dca36c354d1ae61f
因此,在我多次尝试,证书签名还是验证不通过证书链验证的情况下,我是这样操作的:
echo a87a2d6dec4d07bd9095c9b2ee73b2ea > serial
不过,目前位置,我暂时也能确定这个属性对于我的需求是否有影响。大家需要的时候也可以再观察观察。
2.2.2生成根证书的证书请求文件
创建根证书请求文件使用openssl req命令。
该命令主要的功能有,生成证书请求文件, 查看验证证书请求文件,还有就是生成自签名证书。生成证书请求需要什么:申请者需要将自己的信息及其公钥放入证书请求中。但在实际操作过程中,所需要提供的是私钥而非公钥,建议使用CA的私钥文件/etc/pki/CA/private/cakey.pem来创建待自签署的证书请求文件,虽非必须,但方便管理。在生成证书请求文件时,就会根据配置文件里要求的整合素必须项进行输入设置。另外,还需要将提供的数据进行数字签名
(使用单向加密),保证该证书请求文件的完整性和一致性,防止他人盗取后进行篡改。
openssl req命令参数说明:
-new :说明生成证书请求文件 -x509 :说明生成自签名证书 -key :指定已有的秘钥文件生成秘钥请求,只与生成证书请求选项-new配合。 -newkey :-newkey是与-key互斥的,-newkey是指在生成证书请求或者自签名证书的时候自动生成密钥, 然后生成的密钥名称由-keyout参数指定。当指定newkey选项时,后面指定rsa:bits说明产生 rsa密钥,位数由bits指定。 如果没有指定选项-key和-newkey,默认自动生成秘钥。 -out :-out 指定生成的证书请求或者自签名证书名称 -config :默认参数在ubuntu上为 /etc/pki/tls/openssl.cnf, 可以使用-config指定特殊路径的配置文件 -nodes :如果指定-newkey自动生成秘钥,那么-nodes选项说明生成的秘钥不需要加密,即不需要输入passphase. -batch :指定非交互模式,直接读取config文件配置参数,或者使用默认参数值 |
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out careq.pem -days 730 -config /etc/pki/tls/openssl.cnf #使用-key指定使用的根证书的私钥文件 /etc/pki/CA/private/cakey.pem,-config指定配置文件 /etc/pki/tls/openssl.cnf ; -days 730指定有效期为730天 ;-out careq.pem指定输出文件为当前命令执行目录下careq.pem
生成证书请求文件时,要求输入配置文件里设定的必须的信息值。如在上文中我配置了要求countryName、stateOrProvinceName、organizationName三个是一致的,因此此时这三者是需要填写,并且记住的。其中对于最终生成的根证书来说这些填写的信息最终体现在证书的详细信息中:
在证书详细信息中、各参数含义如下:
C-----国家(Country Name)
S----省份(State or Province Name)
L----城市(Locality Name)
O----公司(Organization Name)
OU----部门(Organizational Unit Name)
CN----通用名(Common Name)
emailAddress----邮箱(Email Address)
通过 openssl req 命令生成证书请求文件 :
2.3生成根证书公钥文件并进行自签名
要提供CA自己的证书,测试环境下CA只能自签署,使用"openssl req -x509"、"openssl x509"和"openssl ca"都可以自签署证书请求文件。 自签署的证书就是自签名证书,自签名证书的体现就是:查看证书时,证书的颁发给与颁发者是一致的,如下图所示:
openssl ca命令用法:
openssl ca [-verbose] [-config filename] [-name section] [-startdate date] [-enddate date] [-days arg] [-md arg] [-policy arg] [-keyfile arg] [-key arg] [-passin arg] [-cert file] [-selfsign] [-in file] [-out file] [-notext] [-outdir dir] [-infiles] [-ss_cert file] [-preserveDN] [-noemailDN] [-batch] [-extensions section] [-extfile section] [-subj arg] [-utf8] |
【选项说明:】 -config filename :指定要使用的配置文件,指定后将忽略openssl.cnf中指定的关于ca的配置选项。 -name section :指定使用配置文件中的那个section。指定后将忽略openssl.cnf中的default_ca段。 -in filename :指定要被CA签署的单个证书请求文件。根CA为其他证书签署时使用。 -infiles :该选项只能是最后一个选项,该选项所接的所有参数都被认为是要被签署的证书请求文件,即一次性签署多个请求文件时使用的选项。 -selfsign :自签署。指定-ss_cert选项时该选项被忽略。 -ss_cert filename:将被CA自签署的单个证书文件。也就是说要重新签署证书。 -out filename :证书的输出文件,同时也会输出到屏幕。不指定时默认输出到stdout。 -outdir dir_name :证书的输出目录。指定该选项时,将自动在此目录下生成一个文件名包含16进制serial值的".pem"证书文件。 -cert :CA自己的证书文件。 -keyfile filename:指定签署证书请求时的私钥文件,即CA自己的私钥文件。 -key passwd_value:指定私钥的加密密码。 -passin arg :传递解密密码 -verbose :打印操作执行时的详细信息 -notext :禁止以文本格式将证书输出到"-out"指定的文件中 -days arg :证书有效期限,从创建时刻开始算startdate,有效期结束点为enddate。 -startdate :自定义证书的开始时间,和"-enddate"一起使用可以推算出证书有效期。 -enddate :自定义证书的结束时间。 -md alg :指定单向加密算法 -policy arg :该选项是配置文件中的section内容,该选项指定了证书信息中的field部分是否需要强制提供还是要强制匹配, :或者可提供可不提供。详细的见配置文件说明。 -extensions section:指定当前创建的证书使用配置文件中的哪个section作为扩展属性。 -batch :签署时使用批处理模式,即非交互模式。该模式下不会有两次询问(是否签署、是否提交)。 -subj arg :替换证书请求中的subject,格式/type0=value0/type1=value1/type2=... |
openssl x509 命令:
该X509命令是一个多目的证书效用。它可用于显示证书信息、将证书转换为各种形式、像“迷你 CA”一样签署证书请求或编辑证书信任设置。
ca命令是用于签署证书的,所以它所需要的文件除了配置文件外就是私钥文件和证书请求文件,而签名后生成的文件是证书文件,因此使用"-in"指定的对象是待签署文件,"-infiles"则是指定多个待签署文件,"-keyfile"是指定私钥文件,"-out"是指定输出的证书文件。
执行命令:
openssl req -x509 -new -key /etc/pki/CA/private/cakey.pem -in careq.pem -out caroot.crt -days 3650
进行自签名:
前面我们提到,在证书的配置文件中规定了证书的信息匹配问题,主要体现在这里,生成证书请求文件,当输入的信息不匹配时可能会报错。
做完自签名之后,我们就可以得到一个自签名根证书了。
在完全生成了需要的根证书的私钥文件、证书请求文件、根证书之后,我们就可以再次确认一下配置文件 /etc/pki/tls/openssl.cnf里的私钥文件路径、根证书路径是否是对的。
做完以上操作就已经完成了根证书的设置,接下来只需要进行需要使用的这个证书的私钥生成、证书请求文件的生成、公钥证书的生成、生成需要的pfx格式证书文件、抽取需要的证书链p7b文件,最后通过结合使用pfx格式证书以及p7b证书链,只要能完整的验证证书的完整性,证书目的是可用于签名的就算是达到目的了。
如果是要配置https就可以参考下面的
三、配置apache的https模式(此步骤对于我的目的而言,没啥用,作为知识点放着)
只是作为知识内容放这里,方便后续需要的时候参考。
首先要安装apache的https模式,执行:yum install -y httpd mod_ssl
这种方式安装的文件目录为/var/www/
为了验证后续我们是否配置好了https,我们需要有一个验证机制。简单验证就是建立一个html文件,之后只要通过https://IP/能访问到这个html的内容就可以了。
echo "this is CA" >> /var/www/html/index.html 注意命令中 的空格
此时我们可以重新生成用于配置https的相关证书文件:私钥文件、证书请求文件、公钥证书文件;也可以直接使用我们前面已经产生的根证书文件。 配置的关键点在于:将生成的私钥文件、以及公钥证书文件的路径写入 配置文件:/etc/httpd/conf.d/ssl.conf中。
为了避免证书文件被删除,可以将生成的私钥文件以及公钥证书文件拷贝一下:
将前面生成的公钥证书文件caroot.crt复制到/root/ssl目录下:
pwd
cp /etc/pki/CA/caroot.crt /root/ssl/
cp /etc/pki/CA/private/cakey.pem /root/ssl/
vi /etc/httpd/conf.d/ssl.conf
再 文件里找到 如下内容:
# Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate. If
# the certificate is encrypted, then you will be prompted for a
# pass phrase. Note that a kill -HUP will prompt again. A new
# certificate can be generated using the genkey(1) command.
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /root/ssl/httpd.crt# Server Private Key:
# If the key is not combined with the certificate, use this
# directive to point at the key file. Keep in mind that if
# you've both a RSA and a DSA private key you can configure
# both in parallel (to also allow the use of DSA ciphers, etc.)
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /root/ssl/httpd.key
将SSLCertificateFile以及SSLCertificateKeyFile 分别指向刚刚复制过来的公钥证书文件以及私钥文件,修改之后如下图所示:
至此再确认一下防火墙设置、确认selinux的设定,再启动httpd服务就可以进行验证了。(当然如果要深入应用,我个人认为还需要再深入研究一下这个 /etc/httpd/conf.d/ssl.conf
配置文件)
systemctl status firewalld
setenforce 0
实际使用过程中,需要考虑开启防火墙,而不是简单粗暴的关闭防火墙,所以如果防火墙开着,需要考虑将端口号放行,具体可参考我其他的博文或者网上相关的资料。
systemctl start httpd
systemctl status httpd
此时,通过浏览器访问:https://IP/
这样就表示成功了!
当然如果配置不对,那么就会这样,启动不起来:
四:生成签名证书
4.1生成签名证书私钥文件
需要使用的证书生成私钥文件的方法都是一样的:
openssl genrsa -des3 -out testuser2key.pem 2048 -des3参数表示加密算法为des3 需要输入即将生成这个私钥文件testuser2key.pem的加密密码,请牢记这个密码,后续需要使用到。
现象如下 ,提示输入加密密码并确认输入,两次输入的信息必须是一致的。
4.2生成签名证书的证书请求文件
生成需要使用的签名证书私钥对应的证书请求文件:
openssl req -new -key testuser2key.pem -out testuser2req.csr -days 365 -config /etc/pki/tls/openssl.cnf
-key 指定当前使用的私钥文件、-out 指定当前要生成的证书请求文件的名字,如上述命令均为指向当前目录下的文件。当使用的密钥文件有加密时,就会提示输入加密使用的密码。之后会提示输入这个证书请求文件的主要信息如:
Country Name (2 letter code) [CN]:CN
State or Province Name (full name) []:ChongQing
Locality Name (eg, city) [chongqing]:chongqing
Organization Name (eg, company) [MyOrganization]:MyOrganization
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:userweil
这些信息最终会在证书的详细信息的使用者中展示,如下图所示就是在生成证书请求文件时设置的Common Name为testuser1最终签发的证书,Common Name就是指的颁发给
整体过程图如下:
4.3CA签发 签名证书的公钥证书文件
生成签名证书的公钥证书文件,在生成根证书的时候采用的是自签名,所以是使用的根证书自己的私钥去做签名,如下图所示:
而到这里需要的签名证书的公钥证书文件的时候就需要注意:是用的签名证书的证书请求文件、根证书的公钥证书文件、以及根证书的私钥文件来进行签发:
openssl ca -in testuser2req.csr -cert /etc/pki/CA/caroot.crt -keyfile /etc/pki/CA/private/cakey.pem -out testuser2.crt -config /etc/pki/tls/openssl.cnf
-in 指定当前使用的证书请求文件;-cert 指定当前签发用的根证书的公钥证书文件,-keyfile 指向当前使用的根证书公钥文件对应的根证书私钥文件;-out 指定即将生成的公钥证书文件名,不指定目录的情况下均为当前目录。
这样就得到了crt后缀的公钥证书文件了。
4.4生成签名证书的pfx格式文件
openssl pkcs12 -export -inkey testuser2key.pem -in testuser2.crt -out testuser2.pfx
-in 使用的是签名通过证书请求文件由CA签发的公钥证书文件-inkey 使用的是私钥文件
-out 指定生成的pfx格式文件 不指定路径为当前目录下
4.4.1检测生成的证书
将生成的pfx文件testuser2.pfx、根证书文件caroot.crt通过windows客户端安装检查最终结果如下:
1、安装pfx文件:
此时安装的这个pfx属于个人证书自动选择存储区域即可:
如果安装的是根证书,则要自行选择,将其安装到受信任的根证书颁发机构中。
查看证书:
生成证书请求文件输入的Common Name信息就是颁发给显示的,详细信息里的使用者信息就是全部输入的信息:
当对应的根证书也安装时就能进行验证:
安装的根证书存储位置:受信任的根证书颁发机构里,颁发给与颁发者信息完全一致,是一个自签名的根证书。
证书密钥用法含Digital Signature:
五、生成根证书的证书链p7b文件
鉴于我的任务还需要使用p7b文件去验证证书链,这里说的证书链必然是要包含到根证书信息的,因此使用的是根证书的相关文件进行抽取证书链。可千万别像我傻兮兮的抽的个人证书的,把自己坑的深。。。。
生成p7b命令语法:
openssl crl2pkcs7 [-inform PEM|DER ] [-outform PEM|DER ] [-in filename ]
[-out filename ] [-certfile filename ] [-nocrl ]
选项说明: -inform PEM|DER:输入文件的格式。DER是DER编码的CRL对象。PEM(默认的格式)是base64编码的CRL对象。 -outform PEM|DER:指定文件的输出格式,跟-inform的意思一样。 -in filename:指定CRL文件,不设置此项则从标准输入中获取。 -out filename:指定输出文件,不设置此项则输入到标准输出。 -certfile filename:指定证书文件,PEM格式的证书文件可以包含多个证书,此选项可以多次使用。 -nocrl:不处理crl。一般情况下,输出文件中包含crl信息,设置此选项时,读取时忽略CRL信息,生成的信息不保护CRL信息。 |
要导出的是根证书的证书链文件:
openssl crl2pkcs7 -certfile caroot.crt -outform DER -out caroot.p7b -nocrl
至此需要的签名证书 testuser2.pfx、根证书链caroot.p7b均已生成,经过验证我的应用中可用。
写在最后:这个过程说简单也挺难的,很多资料都是属于复制粘贴,有些时候还遇到各种报错,需要更多的时间与精力去研究,并且要研究透彻的话就需要加入自己的思考,每一步为什么是这样,怎么做才是对的,这种操作为什么不行.....各种各样的,过程中差点就放弃了,因为研究了很久就是不能用。还好最后告诉自己:再试一下,然后历时一个星期+,终于搞定了!!!.....有时候坚持不一定有用,不一定是对的,但是想放弃的时候再坚持一下还是有用的。