使用OpenSSL创建自己的CA root certificate
在密码学中,CA(Certificate Authority,认证机构)是指一个被多个用户信任的机构,该机构能够创建和指派公钥证书。
为规范起见,我们先介绍本文可能涉及的术语,
asymmetric cryptography: 非对称密码学(或公开密钥加密,公钥加密),密钥涉及公钥和私钥组成的密钥对;
key pair: 密钥对,非对称密码学中的一对公/私密钥;
private key: 私钥,只应该有所有者才知道的那个密钥;
public key: 公钥(公开密钥),在非对称加密体系中公开给其他用户的的密钥;
public key certificate:公开密钥证书,由认证机构采用自己的私钥进行数字签名后的用户公钥证书,包含用户的公钥和身份信息,用于确认公钥证书持有者的身份;
CA: 认证机构,能够颁发公开密钥证书的机构;
PKI: 公开密钥基础设施(public key infrastructure);
许多涉及电子交易或电子转账的网站都需要确保用户安全地连接到自己网站。为了达到这一目的,这些单位需要由一些国际认可的CA(如,VeriSign等)来为自己颁发公钥证书。这些证书被用于建立SSL连接或解密电子签名等用途。申请证书的过程需要经过CA的实地认证,同时为CA支付不菲的认证费用。
对于仅仅搭建一个VPN或内网环境的应用场景,这样的开销与周期显然是不必要的,因此在一些特定环境下我们只需要自己为自己颁发的公钥证书即可。本文就介绍如何担任自己的CA也即是自己“创办”一个实验的CA机构。
本文中我们采用/etc/pki/CA作为保存私钥和公钥证书的根目录,为了方便起见下文统称该目录为“证书根目录”。
我们的实验环境是Ubuntu 14.04 LTS, 但在其他的Linux平台上也应该同样适用,操作系统需要安装OpenSSL,同时该部分的操作要以系统管理员的身份进行,因此下文中的命令行统一采用"#"标识符打头。
在安装OpenSSL后,系统会在/etc/ssl/目录下生成openssl.cnf文件(不同的操作系统可能位于不同的目录),我们后面需要用到这个文件。
首先我们要在证书根目录下创建一些子目录,为了后续操作的方便,这些目录的命名遵循openssl.cnf的命名方式,还要在证书根目录下创建index.txt和serial文件用于追踪密钥和证书的记录:
# mkdir /etc/pki/CA
# cd /etc/pki/CA
# mkdir certs crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
上面的指令在我们的证书根目录下创建了四个新目录和两个追踪文档,在创建完目录后及时更改权限是一个很好的习惯。
这里private/目录将存放我们未来创建的CA根私钥,该私钥需要受到严格保护,一旦该私钥泄露,任何获得该私钥的人员均可以利用其创建证书,所以下文中我们将对其进行加密。
同时,如果将本文的操作应用于小型生产或局域网环境,理想的情况是在生成该目录中的CA根私钥前断开网络连接,将生成后的内容保存到不接入网络的存储介质如U盘等,只有在后续需要使用的时候再连入主机。
接下来我们要生成自己的CA私钥,下面的命令采用AES-256算法加密CA根私钥,将其保存在private/ca.key.pem文件中,为避免误改,将文件置为只有管理员可读的状态。
由于选择了加密CA私钥,在生成该私钥时要求输入使用密码,该密码用于在后续使用CA根私钥时解密获得CA私钥,因此该密码应由创建CA私钥的输入并妥善保存。
# openssl genrsa -aes256 -out /etc/pki/CA/private/ca.key.pem 4096
Enter pass phrase for ca.key.pem:SECRET
Verifying - Enter pass phrase for ca.key.pem:SECRET
# chmod 400 /etc/pki/CA/private/ca.key.pem
接下来我们利用OpenSSL为自己创建公钥证书,假设保存为ca.cert.pem,首先进行公钥证书创建前的配置,
# cd /etc/pki/CA # cp /etc/ssl/openssl.cnf root_CA.cnf # vim root_CA.cnf
模板中的配置项需要进行适当的修改,确保以下字段被设置:
[ CA_default ]
dir = /etc/pki/CA
certs = $dir/certs
private = $dir/private
certificate = $certs/ca.cert.pem
private_key = $private/ca.key.pem
[ usr_cert ] # CA签名时常用的扩展 basicConstraints=CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer [ v3_ca ] # CA的一些典型扩展 subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer basicConstraints = CA:true keyUsage = cRLSign, keyCertSign
接下来创建公钥证书,
# cd /etc/pki/CA
# openssl req -new -x509 -days 3650 -key private/ca.key.pem \
-sha256 -extensions v3_ca -out certs/ca.cert.pem \
-config root_CA.cnf
上面的一条命令指定了我们要为之前创建的CA根私钥颁发公钥证书,该证书的有效期是10年,采用SHA-256算法生成消息摘要,同时由于这是一个CA证书,需要在命令中指明采用v3_ca扩展,该扩展的具体配置已经在root_CA.cnf文件中设置,采用-config选项包括配置文件。
该命令执行后首先要求我们输入前文中设置的CA私钥密码,还需要声明自己的一些身份信息:
Enter pass phrase for ca.key.pem: You are about to be asked to enter information that will be incorporated into your certificate request. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:Beijing Locality Name (eg, city) [Default City]:Beijing Organization Name (eg, company) [Default Company Ltd]:Alice CA Organizational Unit Name (eg, section) []:Certificate Authority Common Name (eg, your name or your server's hostname) []:Alice CA Email Address []:alice@example.com
当这些信息输入完成后,生成的公钥证书ca.cert.pem就导入到certs/目录下了。
这样我们就自己创建了一个CA,拥有了该CA的私钥和公钥证书,接下来,我们可以直接使用这个CA私钥和证书签名和颁发客户证书,也可以利用该根私钥和公钥证书创建中间认证机构,中间认证机构是我们这里CA的代理,能够代表我们刚创建的CA签发客户证书。创建中间CA的优点在我们不使用CA根私钥而是使用中间CA的私钥来签发客户证书,CA根私钥只用来签发中间CA的证书撤销列表,这样能够更为妥善地保护CA根私钥。
下面的一篇随笔介绍如何使用根CA创建中间CA并为其颁发证书;
也可以直接利用本文中生成的私钥和证书颁发用户证书。