java https协议访问 handshake_failure,protocol_version问题

一 https访问协议

https网站访问协议安全性由高到底有TLS1.3、TLS1.2、TLS1.1、TLS1.0、SSL,TLS1.3是目前最新的协议,TLS协议建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。在TLS与SSL 3.0之间存在着显著的差别,主要是它们所支持的加密算法不同,所以TLS与SSL 3.0不能互操作

ssl4次握手过程

1 客户端发送支持的加密方式以及一个随机数client random给服务器;

2 服务器选择其中客户端中的一种加密方式,并且再加上另外一个随机数server random,和数字证书(其中有公钥),发送给客户端;

3 客户端确认这个数字证书是有效的,并且再生成一个新的随机数,将这个随机数用服务器发送给它的数字证书中的公钥进行加密发送给服务器;

4 服务器收到客户端的回复,利用自己的私钥进行解密,获得这个随机数,然后通过将前面这三个随机数以及他们协商的加密方式,计算生成一个对称密钥。

https握手详解:https://blog.csdn.net/hherima/article/details/52469674

Java中查看支持的协议及加密方式

1 查看本地支持协议

       SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);

        SSLSocketFactory factory = (SSLSocketFactory) context.getSocketFactory();
        SSLSocket socket = (SSLSocket) factory.createSocket();

        String[] protocols = socket.getSupportedProtocols();

        System.out.println("支持的协议: " + protocols.length);
        for (int i = 0; i < protocols.length; i++) {
            System.out.println(" " + protocols[i]);
        }

        protocols = socket.getEnabledProtocols();

        System.out.println("本地能够支持的协议: " + protocols.length);
        for (int i = 0; i < protocols.length; i++) {
            System.out.println(" " + protocols[i]);
        }

2 查看本地支持的加密方式

SSLServerSocketFactory ssf = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
        TreeMap<String, Boolean> ciphers = new TreeMap<>();
        for (String cipher : ssf.getSupportedCipherSuites()) {
            ciphers.put(cipher, Boolean.FALSE);
        }
        for (String cipher : ssf.getDefaultCipherSuites()) {
            ciphers.put(cipher, Boolean.TRUE);
        }
        System.out.println("加密套件");
        for (Entry<String, Boolean> cipher : ciphers.entrySet()) {
            System.out.println((cipher.getValue() ? "支持 ": "不支持")+"\t "+cipher.getKey());
        }

3 查看服务器支持的协议及加密套件nmap --script ssl-enum-ciphers -p 443 域名地址


image.png

如果nmap未安装可以使用yum install nmap命令安装
4 java中设置协议方式

/**
配置单个https请求的协议类型
*/
private static void initSSLSocketFactory( Connection connection){
        try {
            SSLContext context = SSLContext.getInstance("TLSv1.2");//设置协议
            context.init(null, new X509TrustManager[] { new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            } }, new SecureRandom());
            connection.sslSocketFactory(context.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/**
配置所有https请求的协议类型
*/
private static void initSSLReq() {
        try {
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(null, new X509TrustManager[] { new X509TrustManager() {

                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            } }, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

三 java输出ssl报文有两种方式

1 使用jvm参数
-Dssl.debug=true -Djavax.net.debug=all
2 使用代码实现

System.setProperty("javax.net.debug","all");
System.setProperty("ssl.debug","true");

四 java中https协议访问问题

1 如果本地协议和服务器协议不匹配则会抛出javax.net.ssl.SSLException: Received fatal alert: protocol_version


image.png

2 如果协议匹配,加密方式没有匹配的就会抛出handshake_failure,握手失败


image.png

3 java中支持的加密方式,在jdk1.8.0_151之前默认做了很多加密长度限制的裁剪,需要下载对应的“Java Cryptography Extension (JCE) Unlimited Strength”包,覆盖jdk安装目录下\jre\lib\security目录下local_policy.jar,US_export_policy.jar
jdkjdk1.8.0_151以后\jre\lib\security\java.security文件,添加配置
crypto.policy=unlimited

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容