最近在研究openssl签发证书,在网上搜索关于openssl的用法、资料等等,总觉得非常分散,而且讲得比较浅,文章虽然不少,但是缺少真正能给你讲的明白得,仅停留在“能用”上,感慨一下,这怎么行,到底是大家也不明白还是秘而不宣呢?
前期建议简单了解下:
tls的概念、单向认证和双向认证过程和区别、数字证书、CA机构的角色、openssl
这里面有两个核心的问题:
我见过的商业案例,客户公网访问某个服务,直接自己签发一个证书,放在服务端,客户https访问也没啥毛病,客户也不怎么在乎。但是如果你的后台服务是给其他公司提供一个接口,而且客户要求双向认证呢?你光有服务端证书那能行么?
还是上面的例子,我的后台给客户的后台双向认证,我可以自建一个根证书,根证书直接签发服务端和客户端证书,到时候服务端证书给我自己,客户端和根证书交给其他公司,也可以实现啊?为啥你还需要多级?
我也不知道理论怎么分析,大概有几点说法:a、根证书作为最权威、最需要保密的证书,一定要离线保证其安全性,因此只暴露中间层证书,这样即使中间证书不慎丢失,也能重新建设新的中间层证书。b、并且作为国际互联网互相认同的证书,如果全都是一个根证书去签发一套产品的客户端服务端证书,那要有多少个根证书?太多了,管不过来了。c、规范,规范,还是tmd规范!你的多级证书管理起来,把安全性吹一吹,不失为一个技术门槛,让你的竞争对手无奈摇头。
另外一个角度,从结果看:目前打开浏览器看看证书,不都是多级证书么?有的还是4级,也不管为啥了,反正实际商业应用中就是这么搞得。
无非就是openssl或openssl的封装,说下优劣:
优势:功能可自定义,能力天花板高,用好了甚至可以写到简历上
劣势:需要对证书有一定的了解、需要对openssl的配置文件有了解
优势:操作简单,不需要太高的专业知识,简单场景对新手比较友好
劣势:不能批量操作,自定义程度差,难以集成
看完了优势劣势,结果显而易见,还是老老实实用原生openssl,虽然难了一些,谁让你的老板花钱雇你研究这个呢?大概研究个1个月就行了,不过最好能翻Q去goo9le一下。CSDN现在的质量越来越差了。
多级证书常用结构如:根证书——中间层证书——服务端/客户端证书,这里的“A——B”表示“A是B的上层证书”或者“A签发了B”
这是具体的证书里面的结构,而对于签发主题,结构是:权威顶层CA机构——中间CA机构——客户端/服务端。这里的“A——B”表示"A负责审核B的信息并确认是否应该签发B的证书"
我们的产品里面最终用的不是根证书和中间层证书,最终交互和验证的是客户端和服务端证书,顶层证书和中间层证书都是为了辅助验证表示“确实有一个权威机构认识你们两个(客户端和服务端)的证书的”。
公网安全访问:如果你公司的产品想在公网上被安全访问,例如HTTPS,那么就需要把你公司的证书拿到权威机构(如Global Sign)去认证一下,权威机构会拿自己的私钥在你的证书上签个字(Global Sign赚的就是这份钱),拿回来的材料就是你的服务端证书,未来客户通过https访问你公司的产品后台,你的后台在握手阶段会先把这个证书发送给客户,客户的电脑在出产时已经安装了权威机构的根证书,客户的浏览器用自己的公钥去验证证书,验证此这证书确实由预置在自己电脑中的根证书签发的,那么这个证书就是有效的,这就完成了服务端证书发给客户端的证书的验证。
服务端安全访问:这个指的是后台服务之间的安全访问,服务之间也需要安全访问,那么多级证书的认证就是一个技术门槛,这个前面提到了,就不说了(我们海外的项目就有这种要求)
我就不说具体操作了,这个文章的意义不在于此,而是和大家交流下大家在建设自己的CA方案的时候遇到的问题。
我自己反正是是自签根证书、根证书签发中间层证书,中间层证书签发客户端、服务端,写了个shell,把openssl的命令行封装了一下,否则每次都需要手动去敲,太麻烦了。
网上能搜到一些建设多级证书的方案,但是有些命令明明就是错的,但是大家都是在摸着石头过河,确实没办法判断出自己签发出来的证书是不是符合要求,你怎么和你的领导说“我做完了”?到时候临使用了,突然发现证书不能用,找问题又没有定位的手段,太被动了。
这里我推荐一个视频,在外网上,自己去看(必看):
https://www.youtube.com/watch?v=d8OpUcHzTeg&list=PLkHWn6amxm3v1HomqB7RxkhQxTNDm_YkF&index=1&t=1371shttps://www.youtube.com/watch?v=d8OpUcHzTeg&list=PLkHWn6amxm3v1HomqB7RxkhQxTNDm_YkF&index=1&t=1371s
网上都在说证书链,到底是个什么,我看也没有讲清楚,证书链有两种理解方法:
a、广义上理解,由于证书的签发关系形成了一条链,而且后续的验证时是从末端逐级向上验证的,最终发现根证书是我们预置且可信的,因此就把这条链称为“证书链”,网上说的大部分证书链都是广义的证书链。
b、具体理解,证书链就是个文件,现在无论是java的框架、curl参数、openssl客户端工具,都会让你指定一个证书文件,那么这个证书文件应该是个证书链,如何制作,很简单,只要把一个证书文件追加到后面一个证书就可以了,这就是证书链。但是用什么证书、哪个证书在前?都是有讲究的。后面第8个问题我们再展开。
得到几个文件:
根证书相关:root.crt、root.key
中间层证书相关:intermediate.crt、intermediate.key
客户端证书:client.crt、client.key
服务端证书:server.crt、server.key
可用的工具有:
服务端:使用nginx开启双向认证功能、openssl的s_server工具、网上找的C写的基于openssl的服务端、java现成的包,python的ssl包自己实现。
客户端:curl工具、openssl的s_client工具、网上找的C写的基于openssl的客户端、java现成的包、python的ssl包自己实现。
具体的命令不说了,照着网上的命令详解或者文档都或多或少很快弄明白。下面说下证书链的问题,这些工具服务端、客户端几乎无一例外都要有三个参数:
参数 | 名称 | 作用 |
---|---|---|
CAfile(也有叫cacert的) | 信任机构证书 | 根证书,验证证书是否是权威机构签发的 |
cert | 客户端/服务端证书 | 用于在ssl握手阶段进行交换验证的证书 |
key | 客户端/服务端私钥 | 用于加密用于对称加密的密钥 |
问题在于,cafile是谁?cert是谁?key是谁?
先说我的结论:“key必须与cert中第一个证书配套,cert可能是server.crt+intermediate.crt或server.crt,cafile可能是intermediate.crt+root.crt或root.crt”,分别讲一下:
如果cert是server.crt,那么key就是server.key这个很容易理解,如果cert是server.crt + intermediate.crt,那么就一定要是intermediate追加到server的后面,这样服务才能正常启动。
cert为server.crt的情况,就如前面我贴的那个视频教程,服务端使用openssl s_server,指定CA文件为intermediate.crt,cert是server.crt,key是server.key,客户端使用curl未指定证书,但是由于他手动把root.crt添加到linux系统中的信任锚中,因此相当于在客户端指定了root.crt,但是注意,他如果未指定客户端证书,那他的这次通讯肯定是单向认证的。
server.crt+intermediate.crt的情况,如这个视频教程的最后一个演示,服务端使用nginx,指定CA文件为root.crt,cert是server.crt+intermediate.crt,key是server.key。客户端仍然是curl,仍然是单向认证。
我在网上也看到了一个不错的C实现的客户端、服务端,我把链接贴出来
Openssl实现双向认证教程(附服务端客户端代码) - 云+社区 - 腾讯云最近一份产品检测报告建议使用基于pki的认证方式,由于产品已实现https,商量之下认为其意思是使用双向认证以处理中间人形式攻击。https://cloud.tencent.com/developer/article/1726029自己上去取代码,这份代码,是双向认证的,服务端启动时,CA文件必须指定为intermediate.crt+root.crt,cert文件为server.crt,key文件为server.key。客户端启动时,CA文件必须指定为intermediate.crt+root.crt,cert文件为client.crt,key文件为client.key。
另外,使用openssl s_server和s_client,也是这样指定的,我顺便吧命令贴一下:
openssl s_server -accept 443 -key server/private/server.key -cert server/certs/server.crt -CAfile intermediate/certs/intermediate_root.crt -state -WWW
openssl s_client -connect 127.0.0.1:443 -CAfile intermediate/certs/intermediate_root.crt -cert client/certs/client.crt -key client/private/client.key -showcerts
对于指定CAfile为intermediate.crt的,目前只发现了在linux下的curl的单向认证场景可以。
踩着坑过来的,还是得多试才行,后面有空再加一点关于证书吊销相关的内容吧