最近在研究基于ssl的传输加密,涉及到了key和证书相关的话题,走了不少弯路,现在总结一下做个备忘

不少人可能听过其中的超过3个名词,但它们究竟有什么关联呢?

  • TLS是 传输层安全协议(Transport Layer Security)的缩写,是一种对基于网络的传输的加密协议,可以在受信任的第三方公证基础上做双方的身份认证。TLS可以用在TCP上,也可以用在无 连接的UDP报文上。协议规定了身份认证、算法协商、密钥交换等的实现。
  • SSL是TLS的前身,现在已不再更新
  • HTTPS是在基于TLS/SSL的安全套接字上的的应用层协议,除了传输层进行了加密外,其它与常规HTTP协议基本保持一致
  • 证书是TLS协议中用来对身份进行验证的机制,是一种数字签名形式的文件,包含证书拥有者的公钥及第三方的证书信息。

证书分为2类:自签名证书和CA证书。一般自签名证书不能用来进行身份认证,如果一个server端使用自签名证书,client端要么被设置为无条件信任任何证书,要么需要将自签名证书的公钥和私钥加入受信任列表。但这样一来就增加了server的私钥泄露风险。

TLS基于CA的身份认证基本原理是:首先验证方需要信任CA提供方自己的证书(CAcert),比如证书在操作系统的受信任证书列表中,或者用户 通过“安装根证书”等方式将 CA的公钥和私钥加入受信任列表;然后CA对被验证方的原始证书进行签名(私钥加密),生成最终的证书;验证方得到最终的证书后,利用CAcert中包含 的公钥进行解密,得到被验证方的原始证书。

根据RSA的加密原理,如果用CA的公钥解密成功,说明该证书的确是用CA的私钥加密的,可以认为被验证方是可信的。

下面我们以客户端单方对服务器端进行身份认证场景,来讲解如何做证书的生成。

证书的生成

证书的生成可以用linux的OpenSSL工具链。对于一个网站,首先必须有自己的私钥,私钥的生成方式为:

openssl genrsa -out ssl.key 

私钥必须妥善保管,既不能丢失,也不能泄露。如果发生丢失和泄露,必须马上重新生成,以使旧的证书失效。

如果要对私钥进行传输/备份,建议先对私钥进行密码加密:

openssl rsa -in ssl.key -des3 -out encrypted.key

利用私钥就可以生成证书了。OpenSSL使用x509命令生成证书。这里需要区分两个概念:证书(certificate)和证书请求(certificate sign request)

  • 证书是自签名或CA签名过的凭据,用来进行身份认证
  • 证书请求是对签名的请求,需要使用私钥进行签名

x509命令可以将证书和证书请求相互转换,不过我们这里只用到从证书请求到证书的过程

从私钥或已加密的私钥均可以生成证书请求。生成证书请求的方法为:

openssl req -new -key ssl.key -out ssl.csr

如果私钥已加密,需要输入密码。req命令会通过命令行要求用户输入国家、地区、组织等信息,这些信息会附加在证书中展示给连接方。

接下来用私钥对证书请求进行签名。根据不同的场景,签名的方式也略有不同

自签名,生成私有证书

自签名的原理是用私钥对该私钥生成的证书请求进行签名,生成证书文件。该证书的签发者就是自己,所以验证方必须有该证书的私钥才能对签发信息进行验 证,所以要么验证方信任一切证书,面临冒名顶替的风险,要么被验证方的私钥(或加密过的私钥)需要发送到验证方手中,面临私钥泄露的风险。

当然自签名也不是一无用处,比如需要内部通讯的两台电脑需要使用加密又不想用第三方证书,可以在两端使用相同的私钥和证书进行验证(当然这样就跟对称加密没有区别了)

自签名的方法为:

openssl x509 -req -in ssl.csr -signkey ssl.key -out ssl.crt

同样如果ssl.key已加密,需要输入密码。

自签名,生成CA证书

CA证书是一种特殊的自签名证书,可以用来对其它证书进行签名。这样当验证方选择信任了CA证书,被签名的其它证书就被信任了。在验证方进行验证时,CA证书来自操作系统的信任证书库,或者指定的证书列表。

生成自签名证书的方法为:

openssl x509 -req -in sign.csr -extensions v3_ca -signkey sign.key -out sign.crt

利用CA证书进行签名

使用CA证书对其它证书进行签名的方法为:

openssl x509 -req -in ssl.csr -extensions v3_usr -CA sign.crt -CAkey sign.key -CAcreateserial -out ssl.crt

花钱购买证书机构的签名

利用上述方法,受信任的机构就可以用自己的私钥(sign.key)对其他人的证书进行签名。我们看到,只需要把证书请求(ssl.csr)发给证书机构,证书机构就可以生成出签名过的证书(ssl.crt)。目前购买证书签名服务的价格大约为100-400元/年。

可选的证书机构有:godaddy startssl namecheap

证书/私钥格式

openssl默认使用PEM格式(形如-----BEGIN CERTIFICATE----- ... ... -----END CERTIFICATE---)存放证书和私钥,nginx/node.js可以使用该格式启动服务。

但使用tomcat或java客户端/android时,不能使用该格式的证书。jdk中包含了一个keytool命令,可以完成整个的证书生成过程,不过这里我们只用openssl工具也可以完成java的支持,即使用PKCS12格式对证书进行打包。

PKCS12格式文件,可以包含多个证书/私钥对,指定多个受信任的server(也可以不包含证书),每个server有一个alias name。我们来看最简单的只包含一个alias的文件生成:

openssl pkcs12 -export -in sign.crt -inkey sign.key -out sign.p12

上面的命令将CA证书及其私钥导出为sign.p12文件,导出时需要指定一个密码。

java客户端程序中对p12文件进行信任

如果我们的服务器使用了自己创建的CA证书签名的证书,或者使用了自签名证书,客户端在使用ssl时,需要将导出的证书文件加入到信任列表中。下面是一段导入证书的示例代码:

 1 javax.net.SocketFactory initSSLSocketFactory(InputStream keyin, char[] password) throws Exception {
2 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS12");
3 keyStore.load(keyin, password);
4 keyin.close();
5
6 javax.net.ssl.TrustManagerFactory trustManagerFactory = javax.net.ssl.TrustManagerFactory.getInstance(javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm());
7 trustManagerFactory.init(keyStore);
8
9 javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("SSL");
10
11 sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
12
13 return sslContext.getSocketFactory();
14 }

我们得到了一个SocketFactory,可以用它来初始化ssl/https连接。

最新文章

  1. Codeforces Round #381 (Div. 2)B. Alyona and flowers(水题)
  2. js搜索框输入提示(高效-ys8)
  3. DB2 UDB DBA 核对清单
  4. 传统认知PK网络认知 刚子扯谈烤串认知
  5. angular 监听ng-repeat结束时间
  6. C++——代码重用
  7. Java基础知识强化之IO流笔记54:IO流练习之 LineNumberReader的特有的功能使用
  8. [LeetCode] 21. Merge Two Sorted Lists 解题思路
  9. NSIS Installer(被NSI脚本编译出来的target)获取命令行参数
  10. javascript数组顺序-----1冒泡的另一种比较好理解的写法
  11. CountDownLatch 源码解析—— countDown()
  12. rpc轻量级框架实例
  13. Vector源码分析和实例应用
  14. 分析攻击IP来源地并画出饼图
  15. centos7安装zabbix4.2
  16. day1作业(格式化输出)
  17. javap 反汇编class文件
  18. SQL Server创建远程链接服务器
  19. 简单复利计算java板
  20. Jexus进程守护工具jws.guard

热门文章

  1. 用最简单的例子理解复合模式(Composite Pattern)
  2. RocketMQ的部署方式及持久化方式
  3. myeclipse 修改freemarker ftl 不重启tomcat
  4. Eclipse中运行Tomcat遇到的内存溢出错误
  5. 四边形优化dp
  6. mybatis查询时间段sql语句
  7. Objective-C:字符串的反转Reverse
  8. 我所遭遇过的游戏中间件--PhysX
  9. android.net.Uri 简介 API
  10. permission 权限 列表 6.0 运行时【案例】