关于TLS的一些基本信息我这里就不多说了,网上一搜一大堆。这里主要说一下,在tls单向认证里,怎么用keytool命令去制作CA证书,签发二级证书。双向认证也就是照着反方向做一遍就好了。
先附一张简单的步骤图,及每一步的命令
1. keytool -certreq -alias server -keystore d:server.keystore -storepass 123456 -file d:server.csr
23. keytool -gencert -alias ca -keystore d:ca.keystore -storepass 123456 -infile d:server.csr -outfile d:server.cer
4. keytool -exportcert -alias ca -keystore d:ca.keystore -storepass 123456 -file d:ca.cer
5. keytool -importcert -alias ca -keystore d:server.keystore -storepass 123456 -file d:ca.cer
6. keytool -importcert -alias server -keystore d:server.keystore -storepass 123456 -file d:server.cer
7. keytool -importcert -alias ca -keystore d:client.keystore -storepass 123456 -file d:ca.cer
一、明确几个文件类型
keystore:密钥库。可以理解为一种数据库,里面存的是受信任的公钥和自己的私钥,可以存多个。服务端和客户端各有一个。常见的文件后缀有keystore,jks,p12等等
csr:证书签名请求文件。是由keystore文件里的自签名证书(后面会说是什么)生成出来的,一般于给CA机构,对该文件进行签名。签名后会变为cer文件。
cer:证书文件。就是一般我们所说的证书了,里面保存了公钥和主体信息。常见的文件后缀有cer,crt,rsa等。
二、生成客户端,服务端,CA,三者的密钥库
因为要模拟单向认证的tls,同时需要CA认证体系,所以我们一共需要三个密钥库。所谓CA,其实本质上就是一个被大家都信任的密钥对所有者。在jdk/bin/目录下,有keytool命令。如果嫌麻烦也可以设置环境变量。
client.keystore
keytool -genkeypair -alias client -keystore d:client.keystore -storepass 123456
说一下每个参数的含义
-genkeypair:生成一个密钥对
-alias:密钥对别名
-keystore:要生成密钥库的路径
-storepass:密钥库密码
然后另外两个密钥库同理:
server.keystore
keytool -genkeypair -alias server -keystore d:server.keystore -storepass 123456
ca.keystore
keytool -genkeypair -alias ca -keystore d:ca.keystore -storepass 123456
现在,我们有了三个文件,客户端的密钥库文件client.keystore,服务端的密钥库server.keystore,CA的密钥库ca.keystore
密钥库中存储的是密钥对,如何查看呢?以client为例, 可以看到,里面有一个别名为client的密钥对了
keytool -list -keystore d:client.keystore -storepass 123456 -v
如果想看详情,在命令后加“-v”,注意此处的证书链长度为1,一会经过CA签发后,会变成2。证书[1]里的所有者和发布者都是自己,这种就叫自签名证书。
三、服务端生成证书签名请求文件
因为我们要做的是tls单向认证,所以是服务端需要到CA去进行签名认证。
服务端需要通过自己的server.keystore,来生成一个证书签名请求文件(*.csr),给到CA去。
keytool -certreq -alias server -keystore d:server.keystore -storepass 123456 -file d:server.csr
会发现,d盘根目录下,多了一个csr文件
四、CA对证书请求文件进行签发
作为CA,你会收到用户(也就是需要被CA签发的机构,这里是指服务端)给你的csr文件,你需要用自己的ca.keystore密钥库中的密钥对,对这个csr文件进行签发
keytool -gencert -alias ca -keystore d:ca.keystore -storepass 123456 -infile d:server.csr -outfile d:server.cer
签发后,就会生成一个cer证书文件。需要把这个cer文件还给服务端。
五、服务端需要将cer证书导入到自己的密钥库中
服务端需要将CA给自己的server.cer,导入到自己的server.keystore中。
注意,这里有个坑!因为我们的CA也是自己的,它并不被任何人信任。如果你试图直接将server.cer文件导入到server.keystore文件中,会报错如下:无法从回复中建立链
所以在导入cer文件前,需要让CA先生成自己的自签名证书,导入到服务端的密钥库中(其实客户端也需要导入,但这里不导入不会影响什么,我们下面第六步再做)
CA先要生成自己的自签名证书文件,直接一步,用自己ca.keystore,生成了cer文件,不用再生成csr文件。
keytool -exportcert -alias ca -keystore d:ca.keystore -storepass 123456 -file d:ca.cer
服务端需要将ca.cer导入到自己的server.keystore文件中
keytool -importcert -alias ca -keystore d:server.keystore -storepass 123456 -file d:ca.cer
接下来就可以导入,第四步里CA给我的cer文件了。可以看到,不再报错
导入的时候,起的别名一定要和导出csr文件时用的密钥对一致,我这里的别名是server。别名一致的时候,才能让原有的证书变成证书链。
keytool -importcert -alias server -keystore d:server.keystore -storepass 123456 -file d:server.cer
这个时候,我们再看服务端密钥库里,server密钥对的详情,就会发现变成了证书链,长度变成了2。现在的证书[1]发布者,也变成了CA。原来的证书[1],就变成了下面的证书[2]
keytool -list -keystore d:server.keystore -storepass 123456 -v
六、将CA的ca.cer导入到客户端的密钥库中
第五步说了,ca.cer不光要导入到服务端的密钥库中,也需要导入到客户端的client.keystore中去
keytool -importcert -alias ca -keystore d:client.keystore -storepass 123456 -file d:ca.cer
至此,CA根证书制作完毕,也已经签发了二级证书server.cer。
现在三个密钥库中的情况是:
client中有自己的密钥对“client”,信任的ca证书“ca”
server中有自己的密钥对“server”,信任的ca证书“ca”,其中,“server”证书是一个证书链
ca中有自己的密钥对“ca”
tls单向认证的时候,客户端加载client.keystore文件即可,服务端加载server.keystore即可