https

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了https相关的知识,希望对你有一定的参考价值。

#概述
https 基本过程是
1.客户端发送请求,请求包含客户端支持的非对称加密方式,等等
2.服务器返回公钥(证书)
3.客户端用公钥加密对称密钥后返回给服务器
4.服务器用私钥解密后得到对称密钥,
5.两者用对称密钥通讯
 
 
#证书验证
关于证书,首先证书的作用是为了证明服务端的可靠性,设想一种情景 如果第二步服务端返回的是裸的公钥,没有证书,那么会有怎样的安全问题
服务器----中间人------客户端
如果中间人角色劫持了报文,将自己的公钥发给客户端,那么中间人就可以代替客户端和服务器通讯,起到劫持报文的效果,
那么如果发送的是证书,会怎样验证:
1.假设服务端通过CA的验证,那么服务端证书中就有一个CA对证书的签名,签名方法sign= CA_privateKey(hash(content)),
2.客户端拿到证书之后,对证书hash,得到值之后,用CA_publicKey对证书中签名解码,得到证书的hash,对比两个hash是否相同,
3.如果不通过CA,而是通过CA下的二级组织,那么就逐级解码,直到有一个能解码,
4.所以只要客户没有安装中间人的证书,并且CA私钥不泄露,那么https就是安全的
 
 
#tomcat开启https
###1.  首先用keytool工具产生.keystore文件,这个文件包含公钥私钥,用.keystore文件可以产生.crt的证书文件,只包含公钥,
关于keystore ,crt ,cacerts的概念:keystore是包含公钥私钥的文件,crt是证书(密钥库),只包含公钥,cacerts是jre中信任的证书(密钥库),
这里证书,密钥,密钥库的概念有些混淆,三个概念有点一样,
**生成keystore**
> keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test.keystore" 
>-genkeypair:生成一对非对称密钥;
>-alias:指定密钥对的别名,该别名是公开的;
>-keyalg:指定加密算法,本例中的采用通用的RAS加密算法;
>-keystore:密钥库的路径及名称,不指定的话,默认在操作系统的用户目录下生成一个".keystore"的文件
 
**查看cacerts中的证书**
>keytool -rfc -list -keystore  "%JAVA_HOME%/jre/lib/security/cacerts
>默认密钥changeit
>-list 命令打印证书的 MD5 指纹。而如果指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。

**导出证书**
>keytool -export -alias tomcat -keystore tomcat.keystore -file tomcat.crt 

**导入证书到cacerts**
>keytool -import -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -file tomcat.crt -alias tomcat


**从cacerts删除密钥(需要管理员的权限)**
>keytool -delete -alias tomcat -keystore "%JAVA_HOME%\jre\lib\security\cacerts"

### 2. 在tomcat的server.xml中开启并指定.keystore文件,及密码
```
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
              maxThreads="150" scheme="https" secure="true"
              clientAuth="false" sslProtocol="TLS"
                keystoreFile="g:\tomcat.keystore"  
                keystorePass="123456"
 />
```
指定之后tomcat的https就被开启

#java代码客户端如何处理证书
java的httpsurlConnection 可以进行https连接,但是由于https中客户端需要安装证书,所以java的https证书这一块需要特定操作,
__实例化信任管理器__
```
public class TrustAnyTrustManager implements X509TrustManager{

     
    /* 该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。
    * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String)
    */
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
       
    }

    /*   该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
    * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String)
    */
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        if(Certificates.DLCCertificate!=null && Certificates.DLCCertificate.equals(chain[0])) {
        }else {
            throw new CertificateException();
        }
    }

    /* 返回受信任的X509证书数组。
    * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
    */
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[]{};
    }

}
```
__流读取证书进行验证__
```
        try {
            InputStream inStream = Certificates.class.getResourceAsStream("/config/Certificate/1214316744.crt");
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
            inStream.close();
            DLCCertificate = cert;

        } catch (CertificateException | IOException e) {
            LOG.error("\u52a0\u8f7d\u8bc1\u4e66\u5931\u8d25");//加载证书失败
        }
   
```
X509Certificate 的equals方法可以进行证书的比较
__安装证书到jre__
用keytool工具加载到cacerts之后就可以不再用自己验证了,但是要注意一点keytool生成ketstore时名字姓氏要写域名,如果是IP,在连接时会不符合,可以实现HostnameVerifier来忽略这一步

***
**补充内容和参考**
关于双向 单向
我们知道TLS协议中验证证书可以是双向的,即服务端也要验证客户端的身份来防止客户端的伪冒,
但是这种场景在一般基于web的https中很少(通过U盾的网银是例外,
U盾其实就是客户端证书,但这样也非常繁琐),因为基于web的应用客户数量大,
很难为每个客户去提供相应的数字证书。但是对于一些企业之间的对接,出于安全考虑,
很多情况下会采用双向认证的方式,因为对于两个企业来说也不存在client、server端的说法。

关于巨复杂的对称密钥生成方法
http://www.jianshu.com/p/a766bbf31417
关于握手
http://blog.csdn.net/hherima/article/details/52469674
关于keytool
http://ln-ydc.iteye.com/blog/1335213




以上是关于https的主要内容,如果未能解决你的问题,请参考以下文章

HTTPS 协议

HTTPS原理

https的实现

HTTP和HTTPS

浅析https

网络相关