生成PKI公私密钥对及数字证书
PKI体系是数字证书的基础。
有些情形只需要公私密钥对就够了, 不需要数字证书,比如私有的SSH服务。但是对于一些要求身份认证的情形,则需要对公钥进行数字签名形成数字证书。
公私密钥对(key pair)
有两种常见的工具来生成RSA公私密钥对,ssh-keygen和openssl genrsa。其实ssh-keygen底层也是使用openssl提供的库来生成密钥。
ssh-keygen
生成2048位RSA密钥对,1024已经不算安全了,现在至少要使用2048位的密钥。
1 | $ ssh-keygen -b 2048 -t rsa -f foo_rsa |
-b 指定密钥位数
-t 指定密钥类型rsa,dsa或者ecdsa。一般常用的就是rsa,据说椭圆曲线ecdsa安全又高效,不过没用过。
如果密钥对用于ssh,那么习惯上私钥命名为id_rsa,对应的公钥就是id_rsa.pub,然后可以使用ssh-copy-id把密钥追加到远程主机的.ssh/authorized_key文件里。
1 | $ ssh-copy-id -i ~/.ssh/id_rsa.pub user@host |
默认生成的密钥对是RFC 4716/SSH2格式,可以转到PEM格式公其他程序使用:
1 | $ ssh-keygen -f id_rsa.pub -e -m pem |
-m 指定转换后的格式,支持RFC4716(RFC 4716/SSH2 public or private key),PKCS8(PEM PKCS8 public key)或PEM(PEM public key)
genrsa
生成2048位rsa私钥:
1 | $ openssl genrsa -des3 -out foo_rsa 2048 |
-des3 用于指定使用三重des加密的私钥访问口令(passphase),每次使用私钥时需要提供正确的口令。
生成的PEM编码格式的私钥类似这个样子:
1 | $ cat foo_rsa |
以上生成的只是私钥,可以进一步根据私钥推导出对应公钥,为什么可以推导出公钥?参见[3]
在Openssl中RSA是内存结构。如果内存结构中有rsa->n,rsa->e时,该RSA是公钥RSA。RSA的私钥只要有是rsa->n, rsa->d 就可以了。但是,往往在应用中,RSA的私钥是也包括rsa->p,rsa->q,rsa->dmp1,rsa->dmq1,rsa->iqmp,你想想,d,n,p,q,p-1,q-1以及(p-1)*(q-1)都有了,推导出e太难吗?人们常说不能从私钥导出公钥,是指产生RSA后,抛弃掉p,q的情况的,没有p,q是无法从公钥中算出私钥的,也无法从私算出公钥的。题外话,公钥是公开的,不必费心思去计算了。
是的,公钥本身就是对外公开,只要私钥还在就没什么大不了的。
推导出对应的公钥:
1 | $ openssl rsa -in foo_rsa -pubout > foo_rsa.pub |
也可以使用ssh-keygen来导出公钥:
1 | $ ssh-keygen -f foo_rsa -y > foo_rsa.pub |
这样导出来的公钥是SSH2格式的。
自签数字证书
有了密钥对,还可以进一步申请数字证书。但向CA申请数字证书是要花钱的,so so,如果没有十分的必要,玩个不用建CA的简单自签吧。
1 | $ openssl req -new -outform PEM -out foo_rsa.cert -key foo_rsa -inform PEM -days 365 -x509 |
参数:
-new 产生一个新的证书请求,会提示用户输入一些相关的信息。如果没有指定-key参数,会生成一个新的RSA私钥。
-days 申请证书的有效期
-outform 输出证书的编码格式,PEM或DER,默认PEM
-key 用户私钥
-inform 用户私钥格式,PEM或DER,默认PEM
-x509 输出一个自签的证书而不是产生一个证书请求文件。这通常用于产生一个测试证书或者一个自签根CA证书(root CA Cert)。如果要添加扩展需要通过配置文件指定。除非指定-set-serial选项,否则使用0作为证书序列号
输入一些信息后就可以生成自签的证书foo_rsa.cert了。
还以一并生成私钥并生成证书,不用提前生成密钥了,不过命令行就更复杂了:
1 | $ openssl req -new -outform PEM -out bar_rsa.cert -newkey rsa:2048 |
这里有几个新参数:
-newkey rsa:nbits 产生一个新的RSA私钥用于生成证书,私钥的位数用nbits指定
-nodes 新产生的私钥不使用des加密的口令,nodes是no des之意。
更详细的用法参考man req。
自建CA中心
自建CA中心,你就可以做CA了,可以签署一系列的数字证书,除了没人内置你的CA root证书之外,一切都不会有问题。
不用担心,CA的根证书也都是自签的,只不过信任度有差异而已:-)
CA的配置文件在/etc/ssl/openssl.cnf,里面指定了建立CA中心需要使用的目录结构和文件。使用默认配置:
1 | $ mkdir -p ~/demoCA/{crl,private,newcerts} |
将CA的私钥foo_rsa拷贝到demoCA/private/cakey.pem,或直接生成到这个目录,默认配置下名字必须为cakey.pem。
生成证书申请文件CSR:
1 | $ openssl req -new -days 365 -key ~/demoCA/private/cakey.pem -out ca.csr |
这里提供的是私钥,回答一些问题就可以生成PEM格式编码的证书请求文件ca.csr了。
自签CA根证书
1 | $ openssl ca -selfsign -in ca.csr |
因为生成证书请求是没有填写任何信息,所以有最后一句的提示。生成的CA根证书为demoCA/cacert.pem,这样你也成为CA认证中心了:-)。/usr/lib/ssl/openssl.cnf是符号链接,链接到/etc/ssl/openssl.cnf。
这是使用自己的私钥为自己的公钥进行数字签名生成数字证书,其实所有的CA都是这么干的。
签署其他证书
有了CA根证书,就可以使用这个根证书来签署其他数字证书了。
和签署CA根证书过程基本一样,只是最后签署证书就不要自签了,因为要用CA根证书签署:
1 | $ openssl ca -in userreq.csr -out usercert.cert |
userreq.csr 为数字证书申请文件
usercert.cert 为使用CA根证书签署后的数字证书
ssh-keygen证书
ssh-keygen也可以生成证书,但是openssh的证书与X.509证书是不同的,它更简单。ssh-keygen支持用户和主机两种证书。这种证书只是在ssh环境下做用户和主机的认证之用。我们常用的还是X.509证书,关于openssh证书的详细信息参见man ssh-keygen CERTIFICATES节。
Refereneces:
[1]基于 OpenSSL 的 CA 建立及证书签发
[2]Openssl生成根证书、服务器证书并签核证书
[3]openssl genrsa 能够单独生成私钥还能推导出公钥的原因
===
[erq]