SSL with Java
HttpsClient所需要的knowledge
terminology
对称加密
加密和解密使用的密钥是相同的。
非对称加密
加密和解密使用的密钥是不相同的。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。
数字证书
针对非对称加密中,如何将公钥给客户端,客户端怎么信任这个公钥的安全性。因此,就出现了数字证书。
就如certificate含义一样,证书是由权威部门颁发的,它是可以信任的。那证书里有什么呢?当然要有公钥,其次是颁发机构和有效期。这有点像身份证,公钥是身份证号,机构是公安局,有效期是多少年。
证书内容具体如下:
- issuer:证书的发布机构
- valid from/to:证书有效期
- public key:公钥
- subject:证书的所有者,即是这个证书是发布给谁的
- fingerprints:指纹。通过指纹算法 计算整个证书的hash值放在证书中。它是用来保证,证书内容没有被修改过。
- signature algorithm:签名算法。有了指纹后,CA机构通过自己的私钥,将指纹和指纹算法加密后,放到证书中。CA加密的过程就是签名,加密的算法就是签名算法。
上面其实指出了cert怎么生成的,CA(Certificate Authority)会将issuer、valid from/to、public key、subject信息放到证书里,再用指纹算法计算一个hash值放在cert中(类似计算文本摘要,保证内容未被修改),最后通过自己的私钥将指纹和指纹算法签名后放在cert中(非对称加密 强保证了指纹的安全性)。
这样又有了新问题,要想验证证书是否合法,需要CA1的公钥,但怎么获取CA1公钥,怎么判断CA1公钥是正确的。
所以,为了确保上面的2个问题,就需要更牛的CA2用私钥给它签名,形成CA1证书。说CA2更牛,是因为用root CA的私钥去签名形成了CA2证书,它是可以通过root CA的公钥去验证的。
到此,就会发现 通过证书已经形成了一条信任链。这条信任链的根部就是root CA的根证书(会内嵌在操作系统或浏览器中)。而CA2的证书就是中介证书,它连接着CA1的证书。因此解密流程是:通过root CA的公钥解密CA2,成功继续解密CA1,获取最终通信公钥。所以,一般在访问https网站后,服务器会发送你end-user证书和中介证书,而rootCA证书浏览器中含有。
最后总结一下,要验证信任链中的某个证书的合法性,需要它issuer的公钥去解密。
X509
它是管理证书格式和用法的一个规范
PEM
它是一种编码方式采用base64,用于keys和certificates encoding。
PKCS12和JKS
它们都是将多组key和cert储存起来,并用密码保护起来的存储容器。
PKI
public key infrastructure公开密钥建设。有点抽象,简要说来,它是一种机制,可以保障网络间的通信安全。实现它的关键,就是公开public key形成证书。详解
Self-signed Certificates
自签发证书:它们不是被其他CA签名,而是证书创建者自己签发的。所有的根证书都是self-signed。所以,它的trust chain length = 1。
实践
上面理论太抽象,下面通过OpenSSL模拟证书的签发过程
搭建root CA和intermediate CA
照着上面的文章做,生成root CA cert和intermediate CA cert,然后用intermediate CA来签发 client的证书。
主要用到命令:
|
|
测试验证cert
|
|
注意我们的openssl server启动后,client就可以模拟浏览器一样,通过Root CA cert校验server发来的证书并建立连接。同时通过浏览器访问https://localhost:12345 也可以看到Certificate trust chain 如下:
one-way-ssl & two-way-ssl
一般的web应用采用的是单向SSL,因为用户数目广泛,且无需在通讯层对用户身份进行验证,一般都在应用逻辑层来保证用户的合法登入。
但是对于企业应用对接,可能会要求对客户端做身份验证。这时就需要做SSL双向认证。
我们上面的实践,是在模拟web网站SSL单向认证的步骤,大概清楚了证书签发的流程 与 trust chain是怎么运作的,后面通过java代码实现单向与双向的SSL认证。
java client
首先前提,我们模拟简单的self-signed SSL证书,也就是说trust chain length=1的情况。并测试了单向和双向SSL通信可能会遇到的问题。详见:HttpClient模拟代码
这里只介绍Java生态 SSL相关知识点:
truststore
一个文件,包含了许多根证书,通过它来验证信任其他证书。jre/jdk默认的truststore位置$JAVA_HOME/lib/security/cacerts
查看它的命令是:keytool -list -keystore $JAVA_HOME/lib/security/cacerts
,默认密码是:changeit
keystore
一个文件,存储ssl通信时,所需要的私钥和证书。如果你是一个建立SSL上的server,证书用来发送给client,私钥则用来解密https建立连接时 客户端发来的对称加密密钥。
注意,这里不再引出https单向认证和双向认证具体过程,只要记住非对称加密只是在HTTPS建立连接时候,用来加密对称加密密钥的手段,所以HTTPS最终是通过对称加密通信。
config
针对HttpClient有代码级的配置,这里只记录一下针对jvm的配置:
|
|
keytool
Keytool is a utility bundled with the JRE for managing key pairs and certificates. This allows us to view/modify/create certificate stores in the Java world.
常用命令:
|
|