精华内容
下载资源
问答
  • java 实现https

    2016-08-18 14:41:02
    摘 要 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问。但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点。本文在简要介绍JSSE的基础上...
    
    

    摘 要 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问。但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点。本文在简要介绍JSSE的基础上提出了两种解决该问题的方法。

      引言

      过去的十几年,网络上已经积累了大量的Web应用。如今,无论是整合原有的Web应用系统,还是进行新的Web开发,都要求通过编程来访问某些Web页面。传统的方法是使用Socket接口,但现在很多开发平台或工具如.NET、Java或PHP等都提供了简单的Web访问接口,使用这些接口很容易编程实现与Web应用系统的交互访问,即使要访问那些采用了HTTPS而不是HTTP的Web应用系统。

      HTTPS,即安全的超文本传输协议,采用了SSL技术,被广泛使用以保证Web应用系统的安全性。访问Web应用的编程接口大多封装了SSL,使得访问HTTPS和访问HTTP一样简单。但是很多中、小型应用系统或基于局域网、校园网的应用系统所使用的证书并不是由权威的认证机构发行或者被其验证,直接使用这些编程接口将不能访问HTTPS。

      本文将在简要介绍JSSE的基础上,详细描述使用JSSE访问HTTPS的方法,主要说明了如何访问带有未经验证证书的HTTPS站点。

      JSSE简介

      Java安全套接扩展 (Java Secure Socket Extension, JSSE)是实现Internet安全通信的一系列包的集合。它是一个SSL和TLS的纯Java实现,可以透明地提供数据加密、服务器认证、信息完整性等功能,可以使我们像使用普通的套接字一样使用JSSE建立的安全套接字。JSSE是一个开放的标准,不只是Sun公司才能实现一个JSSE,事实上其他公司有自己实现的JSSE。

      在深入了解JSSE之前,需要了解一个有关Java安全的概念:客户端的TrustStore文件。客户端的TrustStore文件中保存着被客户端所信任的服务器的证书信息。客户端在进行SSL连接时,JSSE将根据这个文件中的证书决定是否信任服务器端的证书。

      JSSE中,有一个信任管理器类负责决定是否信任远端的证书,这个类有如下的处理规则:

      ⑴ 果系统属性javax.net.sll.trustStore指定了TrustStore文件,那么信任管理器就去jre安装路径下的lib/security/目录中寻找并使用这个文件来检查证书。

      ⑵ 果该系统属性没有指定TrustStore文件,它就会去jre安装路径下寻找默认的TrustStore文件,这个文件的相对路径为:lib/security/jssecacerts。

      ⑶ 如果 jssecacerts不存在,但是cacerts存在(它随J2SDK一起发行,含有数量有限的可信任的基本证书),那么这个默认的TrustStore文件就是cacerts。

      直接使用类HttpsURLConnection访问Web页面

      Java提供了一种非常简洁的方法来访问HTTPS网页,即使用类HttpsURLConnection、URL等。这几个类为支持HTTPS对JSSE相关类做了进一步的封装,例子如下所示:

    URL reqURL = new URL("https://www.sun.com" ); //创建URL对象
    HttpsURLConnection httpsConn = (HttpsURLConnection)reqURL.openConnection();
    
    /*下面这段代码实现向Web页面发送数据,实现与网页的交互访问
    httpsConn.setDoOutput(true); 
    OutputStreamWriter out = new OutputStreamWriter(huc.getOutputStream(), "8859_1"); 
    out.write( "……" ); 
    out.flush(); 
    out.close();
    */
    
    //取得该连接的输入流,以读取响应内容 
    InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream();
    
    //读取服务器的响应内容并显示
    int respInt = insr.read();
    while( respInt != -1){
     System.out.print((char)respInt);
     respInt = insr.read();
    }

    这段代码能够正常执行,然而把访问的URL改为https://login.bjut.edu.cn时,程序将抛出异常javax.net.ssl.SSLException,这是由于https://login.bjut.edu.cn站点的安全证书不被JSSE所信任。根据JSSE简介中对信任管理器的分析,一种解决这个问题的方法是按照信任管理器的处理规则,把站点的证书放到证书库文件jssecacerts中,或者把证书存放到任一TrustStore文件中,然后设置系统属性javax.net.sll.trustStore指向该文件。另一种解决方法则是自己实现信任管理器类,让它信任我们指定的证书。下面分别介绍这两种方法。

      将证书导入到TrustStore文件中

      Java提供了命令行工具keytool用于创建证书或者把证书从其它文件中导入到Java自己的TrustStore文件中。把证书从其它文件导入到TrustStore文件中的命令行格式为:

      keytool -import -file src_cer_file –keystore dest_cer_store

      其中,src_cer_file为存有证书信息的源文件名,dest_cer_store为目标TrustStore文件。

      在使用keytool之前,首先要取得源证书文件,这个源文件可使用IE浏览器获得,IE浏览器会把访问过的HTTPS站点的证书保存到本地。从IE浏览器导出证书的方法是打开“Internet 选项”,选择“内容”选项卡,点击“证书…”按钮,在打开的证书对话框中,选中一个证书,然后点击“导出…”按钮,按提示一步步将该证书保存到一文件中。最后就可利用keytool把该证书导入到Java的TrustStore文件中。为了能使Java程序找到该文件,应该把这个文件复制到jre安装路径下的lib/security/目录中。

      这样,只需在程序中设置系统属性javax.net.sll.trustStore指向文件dest_cer_store,就能使JSSE信任该证书,从而使程序可以访问使用未经验证的证书的HTTPS站点。

      使用这种方法,编程非常简单,但需要手工导出服务器的证书。当服务器证书经常变化时,就需要经常进行手工导出证书的操作。下面介绍的实现X509证书信任管理器类的方法将避免手工导出证书的问题。
    X509证书信任管理器类的实现及应用

      在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。我们可以自己实现该接口,让它信任我们指定的证书。

      接口X509TrustManager有下述三个公有的方法需要我们实现:

      ⑴ oid checkClientTrusted(X509Certificate[] chain, String authType) 
    throws CertificateException

      该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。

      ⑵ oid checkServerTrusted(X509Certificate[] chain, String authType) 
    throws CertificateException 

      该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。

      ⑶ X509Certificate[] getAcceptedIssuers() 

      返回受信任的X509证书数组。

      自己实现了信任管理器类,如何使用呢?类HttpsURLConnection似乎并没有提供方法设置信任管理器。其实,HttpsURLConnection通过SSLSocket来建立与HTTPS的安全连接,SSLSocket对象是由SSLSocketFactory生成的。HttpsURLConnection提供了方法setSSLSocketFactory(SSLSocketFactory)设置它使用的SSLSocketFactory对象。SSLSocketFactory通过SSLContext对象来获得,在初始化SSLContext对象时,可指定信任管理器对象。下面用一个图简单表示这几个JSSE类的关系: 


    假设自己实现的X509TrustManager类的类名为:MyX509TrustManager,下面的代码片断说明了如何使用MyX509TrustManager:

    //创建SSLContext对象,并使用我们指定的信任管理器初始化
    TrustManager[] tm = {new MyX509TrustManager ()}; 
    SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE"); 
    sslContext.init(null, tm, new java.security.SecureRandom()); 
    
    //从上述SSLContext对象中得到SSLSocketFactory对象
    SSLSocketFactory ssf = sslContext.getSocketFactory();
    
    //创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
    HttpsURLConnection httpsConn = (HttpsURLConnection)myURL.openConnection();
    httpsConn.setSSLSocketFactory(ssf);

    这样,HttpsURLConnection对象就可以正常连接HTTPS了,无论其证书是否经权威机构的验证,只要实现了接口X509TrustManager的类MyX509TrustManager信任该证书。

      小结

      本文主要介绍了在HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种方法,一种方法是把该证书导入到Java的TrustStore文件中,另一种是自己实现并覆盖JSSE缺省的证书信任管理器类。两种方法各有优缺点,第一种方法不会影响JSSE的安全性,但需要手工导入证书;第二种方法虽然不用手工导入证书,但需要小心使用,否则会带来一些安全隐患。


    展开全文
  • java实现https免证书认证 解决方法: 1.下载两个包,httpclient-4.2.jar和httpcore-4.2.jar,复制以下代码就可使用。 2.调用类代码: String httpOrgCreateTest = "https://url"; Map<String,Object&...

    java实现https免证书认证

     

    解决方法:

    1.下载两个包,httpclient-4.2.jar和httpcore-4.2.jar,复制以下代码就可使用。

    2.调用类代码:

    String httpOrgCreateTest = "https://url";

       Map<String,Object> createMap = new HashMap<String,Object>();

    createMap.put("name","8888888");

    createMap.put("num","11111");

    createMap.put("array",list.toArray());

        String message = JSON.toJSONString(createMap);

        String result = HttpRequest.sendPost(httpOrgCreateTest, message);

    3.HttpRequest类

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.PrintWriter;

    import java.net.URL;

    import javax.net.ssl.HttpsURLConnection;

    import javax.net.ssl.SSLContext;

    import javax.net.ssl.SSLSocketFactory;

    import javax.net.ssl.TrustManager;

    public class HttpRequest {

     

    public static String sendPost(String url, String param) {

    PrintWriter out = null;

    BufferedReader in = null;

    String result = "";

    try {

     

    // 创建SSLContext对象,并使用我们指定的信任管理器初始化

    TrustManager[] tm = { new MyX509TrustManager() };

    SSLContext sslContext = SSLContext.getInstance("SSL");

    sslContext.init(null, tm, new java.security.SecureRandom());

     

    // 从上述SSLContext对象中得到SSLSocketFactory对象

    SSLSocketFactory ssf = sslContext.getSocketFactory();

     

    // 打开和URL之间的连接

    //URL realUrl = new URL(url);

    URL realUrl= new URL(null, url, new sun.net.www.protocol.https.Handler());

    HttpsURLConnection conn = (HttpsURLConnection) realUrl.openConnection();

    conn.setSSLSocketFactory(ssf);

     

    // 设置通用的请求属性

    conn.setRequestProperty("accept", "*/*");

    conn.setRequestProperty("connection", "Keep-Alive");

    conn.setRequestProperty("content-Type", "application/json");

    conn.setRequestProperty("user-agent",

    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

    // 发送POST请求必须设置如下两行

    conn.setDoOutput(true);

    conn.setDoInput(true);

    // 获取URLConnection对象对应的输出流

    out = new PrintWriter(conn.getOutputStream());

    // 发送请求参数

     

    out.print(param);

    // flush输出流的缓冲

    out.flush();

    // 定义BufferedReader输入流来读取URL的响应

    in = new BufferedReader(

    new InputStreamReader(conn.getInputStream()));

    String line;

    while ((line = in.readLine()) != null) {

    result += line;

    }

    } catch (Exception e) {

    System.out.println("发送 POST 请求出现异常!"+e);

    e.printStackTrace();

    }

    //使用finally块来关闭输出流、输入流

    finally{

    try{

    if(out!=null){

    out.close();

    }

    if(in!=null){

    in.close();

    }

    }

    catch(IOException ex){

    ex.printStackTrace();

    }

    }

    return result;

    }

    }

     

    4.MyX509TrustManager类

    import java.security.cert.CertificateException;

    import java.security.cert.X509Certificate;

    import javax.net.ssl.X509TrustManager;

    public class MyX509TrustManager implements 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 null;

    }

    }

    转载于:https://www.cnblogs.com/chinaifae/p/10188499.html

    展开全文
  • java实现HTTPS工作原理的例子

    千次阅读 2016-09-18 17:13:59
    java实现HTTPS工作原理的例子

    文章来源:https://my.oschina.net/ydsakyclguozi/blog/612886,欢迎大家去看,也感谢作者。

    代码下载地址:http://download.csdn.net/detail/qingqingzijinxin/9632926

    今天被问到关于https原理的问题,结果由于知识掌握不牢靠,停留于表面,很多细节都无法回答清楚,于是决定把https的原理弄个明白,废话不多说,我们先看看https的定义

     (由于很久未写博客,排版有些凌乱,请谅解)

    一:什么是https协议

         在说HTTPS之前先说说什么是HTTP,HTTP就是我们平时浏览网页时候使用的一种协议。HTTP协议传输的数据都是未加密的,也就是明文的,因此使 用HTTP协议传输隐私信息非常不安全。为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering Task Force)定义在RFC 6101中,之后IETF对SSL 3.0进行了升级,于是出现了TLS(Transport Layer Security) 1.0,定义在RFC 2246。实际上我们现在的HTTPS都是用的TLS协议,但是由于SSL出现的时间比较早,并且依旧被现在浏览器所支持,因此SSL依然是HTTPS的 代名词,但无论是TLS还是SSL都是上个世纪的事情,SSL最后一个版本是3.0,今后TLS将会继承SSL优良血统继续为我们进行加密服务。目前 TLS的版本是1.2,定义在RFC 5246中,暂时还没有被广泛的使用。对历史感兴趣的朋友可以参考http://en.wikipedia.org/wiki/Transport_Layer_Security,这里有对TLS/SSL详尽的叙述。

     

    二:https的工作原理是什么

         HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握 手过程中将确立双方加密传输数据的密码信息,通常情况下会配合数字证书实现。

    TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL中使用 非对称加密对称加密以及HASH算法

    这里我们先看看这上面提到的几种技术(如果你对这些技术已经非常了解,那么请跳过该段落,直接到段落三)

    1. 数字证书

            数字证书是一种权威性的电子文档,由权威公正的第三方机构,即CA中心签发的证书。它以数字证书为核心的加密技术可以对网络上传输的信息进行加密和解密、数字签名和签名验证,确保网上传递信息的机密性、完整性。 使用了数字证书,即使您发送的信息在网上被他人截获,甚至您丢失了个人的账户、密码等信息,仍可以保证您的账户、资金安全。 

         它能提供在Internet上进行身份验证的一种权威性电子文档,人们可以在互联网交往中用它来证明自己的身份和识别对方的身份。当然在数字证书认证的过程中证书认证中心(CA)作为权威的、公正的、可信赖的第三方,其作用是至关重要的.如何判断数字认证中心公正第三方的地位是权威可信的。VeriSign、GeoTrust、Thawte 是国际权威数字证书颁发认证机构的“三巨头”,其中,应用最广的为VerSign签发的电子商务数字证书。

    CER(Canonical Encoding Rules,规范编码格式) 是数字证书的一种编码格式,它是BER(Basic Encoding Rules 基本编码格式) 的一个变种,比BER 规定得更严格。后缀的证书文件有两种编码:

    DER(Distinguished Encoding Rule 卓越编码格式) 同样是BER的一个变种,DER使用定长模式。

    PKCS(Public-Key Cryptography Standards,公钥加密标准) 由RSA实验室和其他安全系统开发商为公钥密码的发展而制定的一系列标准。

    pfx是指以pkcs#12格式存储的证书和相应私钥。 

    在Security编程中,有几种典型的密码交换信息文件格式: 
    DER-encoded certificate: .cer, .crt 
    PEM-encoded message: .pem 
    PKCS#12 Personal Information Exchange: .pfx, .p12 
    PKCS#10 Certification Request: .p10 .csr
    PKCS#7 cert request response: .p7r 
    PKCS#7 binary message: .p7b .p7c .spc

    cer/.crt 是用于存放证书,它是2进制形式存放

    pem 跟crt/cer的区别是它以Ascii来表示

    pfx/p12 用于存放个人证书/私钥,他通常包含保护密码,2进制方式 

    p10 .csr 是证书请求 

    p7r是CA对证书请求的回复,只用于导入 

    p7b .p7c .spc 以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥

     

     

    1. 非对称加密算法

              1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是"公开密钥系统"。相对于"对称加密算法"这种方法也叫做"非对称加密算法"。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

           非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要,但加密和解密花费时间长、速度慢,它不适合于对文件加密而只适用于对少量数据进行加密。 经典的非对称加密算法如RSA算法等安全性都相当高. 非对称加密的典型应用是数字签名。采用双钥密码系统的加密方法,在一个过程中使用两个密钥,一个用于加密,另一个用于解密,这种加密方法称为非对称加密,也称为公钥加密,因为其中一个密钥是公开的(另一个则需要保密)。

    DH (Diffie-Hellman)
           Diffie-Hellman算法(D-H算法),密钥一致协议。是由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成"一致"的、可以共享的密钥。换句话说,就是由甲方产出一对密钥(公钥、私钥),乙方依照甲方公钥产生乙方密钥对(公钥、私钥)。以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥(SecretKey)对数据加密。这样,在互通了本地密钥(SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!该算法源于中国的同余定理——中国馀数定理。

    RSA
           RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

    EL Gamal
             EL Gamal算法是公钥密码体制中的一种 ,在密码学中占有重要的地位。但该算法所采用的幂剩余计算耗时太多的问题 ,一直是制约其广泛应用的瓶颈问题。提出一种通过建表 ,以及对传统二进制算法进行改进 ,即将指数进行 2 k进制化 ,减少原 BR算法迭代次数 ,提高加密解密速度的算法。

    ECC 
    ECC (Elliptical Curve Cryptography,椭圆曲线加密)算法不椭圆曲线理论为基础,在创建密钥时可以更快,更小,并且更有效,它是用大质数的积来产生。

    目前Java 6公提供了DH和RSA两种算法实现,通过Bouncy Castle可以实现Elmal算法支持,另ECC加密算法,目前没有开源组件提支持

    1. 对称加密算法

            对加密和解密使用相同密钥的加密算法。由于其速度,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。对称式数据加密的方式的工作原理如图。所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥实际上是一种算法,通信发送方使用这种算法加密数据,接收方再以同样的算法解密数据。因此对称式加密本身不是安全的。常用的对称加密有: 

    DES、IDEA、RC2、RC4、SKIPJACK算法等 。

    采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。

     

    1. HASH算法

    常用的摘要算法包括MD5,SHA1,SHA256

    消息摘要算法的特点:

    ① 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
    ② 消息摘要看起来是“随机的”。这些比特看上去是胡乱的杂凑在一起的。
    ③ 一般地,只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。
    ④ 消息摘要函数是无陷门的单向函数,即只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息。
    ⑤ 好的摘要算法,无法找到两条消息,是它们的摘要相同。

     

    消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性。消息摘要采用单向Hash 函数将需加密 的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致 。这样这串摘要便可成为验证明文是否是"真身"的"指纹"了。


           HASH函数的抗冲突性使得如果一段明文稍有变化,哪怕只更改该段落的一个字母,通过哈希算法作用后都将产生不同的值。而HASH算法的单向性使得要找到到哈希值相同的两个不 同的输入消息,在计算上是不可能的。所以数据的哈希值,即消息摘要,可以检验数据的完整性。哈希函数的这种对不同的输入能够生成不同的值的特性使得无法找到两个具有相同哈希值的输入。因此,如果两个文档经哈希转换后成为相同的值,就可以肯定它们是同一文档。 所以,当希望有效地比较两个数据块时,就可以比较它们的哈希值。例如,可以通过比较邮件发送前和发送后的哈希值来验证该邮件在传递时是否修改


          消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。消息摘要算法不存在 密钥的管理与分发问题,适合于分布式网络相同上使用。由于其加密计算的工作量相当可观,所以以前的这种算法通常只用于数据量有限的情况下的加密,例如计算机的口令就是 用不可逆加密算法加密的。

     

    三 https握手的过程详细描述

    1.浏览器将自己支持的一套加密规则发送给网站,如RSA加密算法,DES对称加密算法,SHA1摘要算法
    2.网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息(证书中的私钥只能用于服务器端进行解密,在握手的整个过程中,都用到了证书中的公钥和浏览器发送给服务器的随机密码以及对称加密算法


    3.获得网站证书之后浏览器要做以下工作:
        a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
        b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
        c) 使用约定好的HASH算法计算握手消息(如SHA1),并使用生成的随机数对消息进行加密,最后将之前生成的被公钥加密的随机数密码,HASH摘要值一起发送给服务器


    4.网站接收浏览器发来的数据之后要做以下的操作:
        a) 使用自己的私钥将信息解密并取出浏览器发送给服务器的随机密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
        b) 使用随机密码加密一段握手消息,发送给浏览器。
        5.浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

     

    从上面的4个大的步骤可以看到,握手的整个过程使用到了数字证书、对称加密、HASH摘要算法,接下来我们用实际代码来实现整个过程

    四 使用java代码模拟整个握手过程

              一:准备工作

                 1、创建java证书,(使用java的keytool工具,在%Java_Home%bin目录下)

                                   C:\> keytool -genkey -alias wangyi -keypass wangyi -keyalg RSA -keysize 1024 -keystore https.keystore -storepass wangyi

                   2、将创建的证书保存到C盘(为了方便演示)

                                 C:\>keytool -export -keystore https.keystore -alias wangyi -file https.crt -storepass wangyi

    二:代码实现

                              代码包含6个类,分别为:

    名称 说明
    CertifcateUtils 证书操作类
    DesCoder Des对称加密和解密工具类
    HttpsMockBase https父类
    HttpsMockClient client类
    HttpsMockServer 服务器类
    SocketUtils socket工具类

    package httpsmock;
    
    import java.io.ByteArrayInputStream;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.cert.CertificateFactory;
    /**
     * Created by kingj on 2014/8/13.
     */
    public class CertifcateUtils {
        public static byte[] readCertifacates() throws Exception{
            CertificateFactory factory=CertificateFactory.getInstance("X.509");
            InputStream in=new FileInputStream("C:\\Users\\baisb1\\keystores\\https.crt");
            java.security.cert.Certificate cate=factory.generateCertificate(in);
            return cate.getEncoded();
        }
    
        public static byte[] readPrivateKey() throws  Exception{
            KeyStore store=KeyStore.getInstance("JKS");
            InputStream in=new FileInputStream("C:\\Users\\baisb1\\keystores\\https.keystore");
            store.load(in,"wangyi".toCharArray());
            PrivateKey pk=(PrivateKey)store.getKey("wangyi","wangyi".toCharArray());
            return pk.getEncoded();
        }
    
        public static PrivateKey readPrivateKeys() throws  Exception{
            KeyStore store=KeyStore.getInstance("JKS");
            InputStream in=new FileInputStream("C:\\Users\\baisb1\\keystores\\https.keystore");
            store.load(in,"wangyi".toCharArray());
            PrivateKey pk=(PrivateKey)store.getKey("wangyi","wangyi".toCharArray());
            return pk;
        }
    
        public static PublicKey readPublicKeys() throws  Exception{
            CertificateFactory factory=CertificateFactory.getInstance("X.509");
            InputStream in=new FileInputStream("C:\\Users\\baisb1\\keystores\\https.crt");
            java.security.cert.Certificate cate=factory.generateCertificate(in);
            return cate.getPublicKey();
        }
    
        public static  java.security.cert.Certificate createCertiface(byte b[]) throws Exception{
            CertificateFactory factory=CertificateFactory.getInstance("X.509");
            InputStream in=new ByteArrayInputStream(b);
            java.security.cert.Certificate cate=factory.generateCertificate(in);
            return cate;
        }
    
        public static String byte2hex(byte[] b) {
            String hs = "";
            String stmp = "";
            for (int n = 0; n < b.length; n++) {
                stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
                if (stmp.length() == 1) {
                    hs = hs + "0" + stmp;
                } else {
                    hs = hs + stmp;
                }
            }
            return hs.toUpperCase();
        }
    }
    

    package httpsmock;
    
    
    import java.security.Key;
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    
    /**
     * DES Coder<br/>
     * secret key length:	56 bit, default:	56 bit<br/>
     * mode:	ECB/CBC/PCBC/CTR/CTS/CFB/CFB8 to CFB128/OFB/OBF8 to OFB128<br/>
     * padding:	Nopadding/PKCS5Padding/ISO10126Padding/
     * @author Aub
     *
     */
    public class DesCoder {
    
        /**
         * 密钥算法
         */
        private static final String KEY_ALGORITHM = "DES";
    
        private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
    //	private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/ISO10126Padding";
    
    
        /**
         * 初始化密钥
         *
         * @return byte[] 密钥
         * @throws Exception
         */
        public static byte[] initSecretKey(SecureRandom random) throws Exception{
            //返回生成指定算法的秘密密钥的 KeyGenerator 对象
            KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
            //初始化此密钥生成器,使其具有确定的密钥大小
            kg.init(random);
            //生成一个密钥
            SecretKey  secretKey = kg.generateKey();
            return secretKey.getEncoded();
        }
    
        /**
         * 转换密钥
         *
         * @param key	二进制密钥
         * @return Key	密钥
         * @throws Exception
         */
        public static Key toKey(byte[] key) throws Exception{
            //实例化DES密钥规则
            DESKeySpec dks = new DESKeySpec(key);
            //实例化密钥工厂
            SecretKeyFactory skf = SecretKeyFactory.getInstance(KEY_ALGORITHM);
            //生成密钥
            SecretKey  secretKey = skf.generateSecret(dks);
            return secretKey;
        }
    
        /**
         * 加密
         *
         * @param data	待加密数据
         * @param key	密钥
         * @return byte[]	加密数据
         * @throws Exception
         */
        public static byte[] encrypt(byte[] data,Key key) throws Exception{
            return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
        }
    
        /**
         * 加密
         *
         * @param data	待加密数据
         * @param key	二进制密钥
         * @return byte[]	加密数据
         * @throws Exception
         */
        public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
            return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
        }
    
    
        /**
         * 加密
         *
         * @param data	待加密数据
         * @param key	二进制密钥
         * @param cipherAlgorithm	加密算法/工作模式/填充方式
         * @return byte[]	加密数据
         * @throws Exception
         */
        public static byte[] encrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{
            //还原密钥
            Key k = toKey(key);
            return encrypt(data, k, cipherAlgorithm);
        }
    
        /**
         * 加密
         *
         * @param data	待加密数据
         * @param key	密钥
         * @param cipherAlgorithm	加密算法/工作模式/填充方式
         * @return byte[]	加密数据
         * @throws Exception
         */
        public static byte[] encrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{
            //实例化
            Cipher cipher = Cipher.getInstance(cipherAlgorithm);
            //使用密钥初始化,设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //执行操作
            return cipher.doFinal(data);
        }
    
    
    
        /**
         * 解密
         *
         * @param data	待解密数据
         * @param key	二进制密钥
         * @return byte[]	解密数据
         * @throws Exception
         */
        public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
            return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
        }
    
        /**
         * 解密
         *
         * @param data	待解密数据
         * @param key	密钥
         * @return byte[]	解密数据
         * @throws Exception
         */
        public static byte[] decrypt(byte[] data,Key key) throws Exception{
            return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
        }
    
        /**
         * 解密
         *
         * @param data	待解密数据
         * @param key	二进制密钥
         * @param cipherAlgorithm	加密算法/工作模式/填充方式
         * @return byte[]	解密数据
         * @throws Exception
         */
        public static byte[] decrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{
            //还原密钥
            Key k = toKey(key);
            return decrypt(data, k, cipherAlgorithm);
        }
    
        /**
         * 解密
         *
         * @param data	待解密数据
         * @param key	密钥
         * @param cipherAlgorithm	加密算法/工作模式/填充方式
         * @return byte[]	解密数据
         * @throws Exception
         */
        public static byte[] decrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{
            //实例化
            Cipher cipher = Cipher.getInstance(cipherAlgorithm);
            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, key);
            //执行操作
            return cipher.doFinal(data);
        }
    
     /*   private static String  showByteArray(byte[] data){
            if(null == data){
                return null;
            }
            StringBuilder sb = new StringBuilder("{");
            for(byte b:data){
                sb.append(b).append(",");
            }
            sb.deleteCharAt(sb.length()-1);
            sb.append("}");
            return sb.toString();
        }*/
    
    }
    

    package httpsmock;
    
    
    import javax.crypto.*;
    import java.security.*;
    import java.util.Random;
    
    /**
     * Created by kingj on 2014/8/13.
     */
    public class HttpsMockBase {
        static PrivateKey privateKey;
        static PublicKey publicKey;
    
    
        public static boolean byteEquals(byte a[],byte[] b){
            boolean equals=true;
            if(a==null || b==null){
                equals=false;
            }
    
            if(a!=null && b!=null){
                if(a.length!=b.length){
                    equals=false;
                }else{
                    for(int i=0;i<a.length;i++){
                        if(a[i]!=b[i]){
                            equals=false;
                            break;
                        }
                    }
                }
    
            }
            return equals;
        }
    
        public static byte[] decrypt(byte data[]) throws Exception{
            // 对数据解密
            Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(data);
        }
    
        public static byte[] decrypt(byte data[],SecureRandom seed) throws Exception{
            // 对数据解密
            Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey,seed);
            return cipher.doFinal(data);
        }
    
        public static byte[] decryptByPublicKey(byte data[],SecureRandom seed) throws Exception{
            if(publicKey==null){
                publicKey=CertifcateUtils.readPublicKeys();
            }
            // 对数据解密
            Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
            if(seed==null){
                cipher.init(Cipher.DECRYPT_MODE, publicKey);
            }else{
                cipher.init(Cipher.DECRYPT_MODE, publicKey,seed);
            }
    
            return cipher.doFinal(data);
        }
    
        public static byte[] decryptByDes(byte data[],SecureRandom seed) throws Exception{
            if(publicKey==null){
                publicKey=CertifcateUtils.readPublicKeys();
            }
            // 对数据解密
            Cipher cipher = Cipher.getInstance("DES");
            if(seed==null){
                cipher.init(Cipher.DECRYPT_MODE, publicKey);
            }else{
                cipher.init(Cipher.DECRYPT_MODE, publicKey,seed);
            }
    
            return cipher.doFinal(data);
        }
    
    
    
    
        public static byte[] encryptByPublicKey(byte[] data, SecureRandom seed)
                throws Exception {
            if(publicKey==null){
                publicKey=CertifcateUtils.readPublicKeys();
            }
            // 对数据加密
            Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
            if(seed==null){
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            }else{
                cipher.init(Cipher.ENCRYPT_MODE, publicKey,seed);
            }
    
            return cipher.doFinal(data);
        }
    
        public static String byte2hex(byte[] b) {
            String hs = "";
            String stmp = "";
            for (int n = 0; n < b.length; n++) {
                stmp = (Integer.toHexString(b[n] & 0XFF));
                if (stmp.length() == 1) {
                    hs = hs + "0" + stmp;
                } else {
                    hs = hs +"  " + stmp;
                }
            }
            return hs.toUpperCase();
        }
    
        public static byte[] cactHash(byte[] bytes) {
            byte[] _bytes = null;
            try {
                MessageDigest md = MessageDigest.getInstance("SHA1");
                md.update(bytes);
                _bytes = md.digest();
            } catch (NoSuchAlgorithmException ex) {
                ex.printStackTrace();
            }
            return _bytes;
        }
    
    
    
        static String random(){
            StringBuilder builder=new StringBuilder();
            Random random=new Random();
            int seedLength=10;
            for(int i=0;i<seedLength;i++){
                builder.append(digits[random.nextInt(seedLength)]);
            }
    
            return builder.toString();
        }
    
        static char[] digits={
                '0','1','2','3','4',
                '5','6','7','8','9',
                'a','b','c','d','e',
                'f','g','h','i','j'
        };
    
    }
    


    package httpsmock;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.Socket;
    import java.security.Key;
    import java.security.SecureRandom;
    
    /**
     * Created by kingj on 2014/8/13.
     */
    public class HttpsMockClient extends  HttpsMockBase {
        static DataInputStream in;
        static DataOutputStream out;
        static Key key;
        public static void main(String args[]) throws  Exception{
            int port=80;
            Socket s=new Socket("localhost",port);
            s.setReceiveBufferSize(102400);
            s.setKeepAlive(true);
            in=new DataInputStream(s.getInputStream());
            out=new DataOutputStream(s.getOutputStream());
            shakeHands();
    
            System.out.println("------------------------------------------------------------------");
            String name="duck";
            writeBytes(name.getBytes());
    
            int len=in.readInt();
            byte[] msg=readBytes(len);
            System.out.println("服务器反馈消息:"+byte2hex(msg));
            Thread.sleep(1000*100);
    
    
        }
    
        private static void shakeHands() throws Exception {
            //第一步 客户端发送自己支持的hash算法
            String supportHash="SHA1";
            int length=supportHash.getBytes().length;
            out.writeInt(length);
            SocketUtils.writeBytes(out, supportHash.getBytes(), length);
    
            //第二步 客户端验证服务器端证书是否合法
            int skip=in.readInt();
            byte[] certificate=SocketUtils.readBytes(in,skip);
            java.security.cert.Certificate cc= CertifcateUtils.createCertiface(certificate);
    
            publicKey=cc.getPublicKey();
            cc.verify(publicKey);
            System.out.println("客户端校验服务器端证书是否合法:" +true);
    
            //第三步  客户端校验服务器端发送过来的证书成功,生成随机数并用公钥加密
            System.out.println("客户端校验服务器端发送过来的证书成功,生成随机数并用公钥加密");
            SecureRandom seed=new SecureRandom();
            int seedLength=2;
            byte seedBytes[]=seed.generateSeed(seedLength);
            System.out.println("生成的随机数为 : " + byte2hex(seedBytes));
            System.out.println("将随机数用公钥加密后发送到服务器");
            byte[] encrptedSeed=encryptByPublicKey(seedBytes, null);
            SocketUtils.writeBytes(out,encrptedSeed,encrptedSeed.length);
    
            System.out.println("加密后的seed值为 :" + byte2hex(encrptedSeed));
    
            String message=random();
            System.out.println("客户端生成消息为:"+message);
    
            System.out.println("使用随机数并用公钥对消息加密");
            byte[] encrpt=encryptByPublicKey(message.getBytes(),seed);
            System.out.println("加密后消息位数为 : " +encrpt.length);
            SocketUtils.writeBytes(out,encrpt,encrpt.length);
    
            System.out.println("客户端使用SHA1计算消息摘要");
            byte hash[]=cactHash(message.getBytes());
            System.out.println("摘要信息为:"+byte2hex(hash));
    
            System.out.println("消息加密完成,摘要计算完成,发送服务器");
            SocketUtils.writeBytes(out,hash,hash.length);
    
    
            System.out.println("客户端向服务器发送消息完成,开始接受服务器端发送回来的消息和摘要");
            System.out.println("接受服务器端发送的消息");
            int serverMessageLength=in.readInt();
            byte[] serverMessage=SocketUtils.readBytes(in,serverMessageLength);
            System.out.println("服务器端的消息内容为 :" + byte2hex(serverMessage));
    
            System.out.println("开始用之前生成的随机密码和DES算法解密消息,密码为:"+byte2hex(seedBytes));
            byte[] desKey= DesCoder.initSecretKey(new SecureRandom(seedBytes));
            key=DesCoder.toKey(desKey);
    
            byte[] decrpytedServerMsg=DesCoder.decrypt(serverMessage, key);
            System.out.println("解密后的消息为:"+byte2hex(decrpytedServerMsg));
    
            int serverHashLength=in.readInt();
            byte[] serverHash=SocketUtils.readBytes(in,serverHashLength);
            System.out.println("开始接受服务器端的摘要消息:"+byte2hex(serverHash));
    
            byte[] serverHashValues=cactHash(decrpytedServerMsg);
            System.out.println("计算服务器端发送过来的消息的摘要 : " +byte2hex(serverHashValues));
    
            System.out.println("判断服务器端发送过来的hash摘要是否和计算出的摘要一致");
            boolean isHashEquals=byteEquals(serverHashValues,serverHash);
    
            if(isHashEquals){
                System.out.println("验证完成,握手成功");
            }else{
                System.out.println("验证失败,握手失败");
            }
        }
    
    
        public static byte[] readBytes(int length) throws  Exception{
            byte[] undecrpty=SocketUtils.readBytes(in,length);
            System.out.println("读取未解密消息:"+byte2hex(undecrpty));
            return DesCoder.decrypt(undecrpty,key);
        }
    
        public static void writeBytes(byte[] data) throws  Exception{
            byte[] encrpted=DesCoder.encrypt(data,key);
            System.out.println("写入加密后消息:"+byte2hex(encrpted));
            SocketUtils.writeBytes(out,encrpted,encrpted.length);
        }
    }
    


    package httpsmock;
    
    import javax.net.ServerSocketFactory;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.security.Key;
    import java.security.SecureRandom;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Created by kingj on 2014/8/13.
     */
    public class HttpsMockServer extends HttpsMockBase {
        static DataInputStream in;
        static DataOutputStream out;
        static String hash;
        static Key key;
        static ExecutorService executorService= Executors.newFixedThreadPool(20);
        public static void main(String args[]) throws Exception{
            int port=80;
            ServerSocket ss= ServerSocketFactory.getDefault().createServerSocket(port);
            ss.setReceiveBufferSize(102400);
            ss.setReuseAddress(false);
            while(true){
                try {
                    final Socket s = ss.accept();
                    doHttpsShakeHands(s);
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            doSocketTransport(s);
                        }
                    });
    
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    
        private static void doSocketTransport(Socket s){
            try{
                System.out.println("--------------------------------------------------------");
                int length=in.readInt();
                byte[] clientMsg=readBytes(length);
                System.out.println("客户端指令内容为:" + byte2hex(clientMsg));
    
                writeBytes("服务器已经接受请求".getBytes());
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    
        public static byte[] readBytes(int length) throws  Exception{
            byte[] undecrpty=SocketUtils.readBytes(in,length);
            System.out.println("读取未解密消息:"+byte2hex(undecrpty));
            return DesCoder.decrypt(undecrpty,key);
        }
    
        public static void writeBytes(byte[] data) throws  Exception{
            byte[] encrpted=DesCoder.encrypt(data,key);
            System.out.println("写入加密后消息:"+byte2hex(encrpted));
            SocketUtils.writeBytes(out,encrpted,encrpted.length);
        }
    
        private static void doHttpsShakeHands(Socket s) throws Exception {
             in=new DataInputStream(s.getInputStream());
             out=new DataOutputStream(s.getOutputStream());
    
            //第一步 获取客户端发送的支持的验证规则,包括hash算法,这里选用SHA1作为hash
            int length=in.readInt();
            in.skipBytes(4);
            byte[] clientSupportHash=SocketUtils.readBytes(in,length);
            String clientHash=new String(clientSupportHash);
            hash=clientHash;
            System.out.println("客户端发送了hash算法为:"+clientHash);
    
            //第二步,发送服务器证书到客户端
            byte[] certificateBytes=CertifcateUtils.readCertifacates();
            privateKey=CertifcateUtils.readPrivateKeys();
            System.out.println("发送证书给客户端,字节长度为:"+certificateBytes.length);
            System.out.println("证书内容为:" + byte2hex(certificateBytes));
            SocketUtils.writeBytes(out, certificateBytes, certificateBytes.length);
    
            System.out.println("获取客户端通过公钥加密后的随机数");
            int secureByteLength=in.readInt();
            byte[] secureBytes=SocketUtils.readBytes(in, secureByteLength);
    
            System.out.println("读取到的客户端的随机数为:"+byte2hex(secureBytes));
            byte secureSeed[]=decrypt(secureBytes);
            System.out.println("解密后的随机数密码为:" +byte2hex(secureSeed));
    
            //第三步 获取客户端加密字符串
            int skip=in.readInt();
            System.out.println("第三步 获取客户端加密消息,消息长度为 :" +skip);
            byte[] data=SocketUtils.readBytes(in,skip);
    
            System.out.println("客户端发送的加密消息为 : " +byte2hex(data));
            System.out.println("用私钥对消息解密,并计算SHA1的hash值");
            byte message[] =decrypt(data,new SecureRandom(secureBytes));
            byte serverHash[]=cactHash(message);
    
    
            System.out.println("获取客户端计算的SHA1摘要");
            int hashSkip=in.readInt();
            byte[] clientHashBytes=SocketUtils.readBytes(in,hashSkip);
            System.out.println("客户端SHA1摘要为 : " + byte2hex(clientHashBytes));
    
            System.out.println("开始比较客户端hash和服务器端从消息中计算的hash值是否一致");
            boolean isHashEquals=byteEquals(serverHash,clientHashBytes);
            System.out.println("是否一致结果为 : " + isHashEquals);
    
    
    
            System.out.println("第一次校验客户端发送过来的消息和摘译一致,服务器开始向客户端发送消息和摘要");
            System.out.println("生成密码用于加密服务器端消息,secureRandom : "+byte2hex(secureSeed));
            SecureRandom secureRandom=new SecureRandom(secureSeed);
    
            String randomMessage=random();
            System.out.println("服务器端生成的随机消息为 : "+randomMessage);
    
            System.out.println("用DES算法并使用客户端生成的随机密码对消息加密");
            byte[] desKey=DesCoder.initSecretKey(secureRandom);
            key=DesCoder.toKey(desKey);
    
            byte serverMessage[]=DesCoder.encrypt(randomMessage.getBytes(), key);
            SocketUtils.writeBytes(out,serverMessage,serverMessage.length);
            System.out.println("服务器端发送的机密后的消息为:"+byte2hex(serverMessage)+",加密密码为:"+byte2hex(secureSeed));
    
            System.out.println("服务器端开始计算hash摘要值");
            byte serverMessageHash[]=cactHash(randomMessage.getBytes());
            System.out.println("服务器端计算的hash摘要值为 :" +byte2hex(serverMessageHash));
            SocketUtils.writeBytes(out,serverMessageHash,serverMessageHash.length);
    
            System.out.println("握手成功,之后所有通信都将使用DES加密算法进行加密");
        }
    
    }
    


    package httpsmock;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    
    /**
     * Created by kingj on 2014/8/13.
     */
    public class SocketUtils {
        public static void close(Socket s){
            try {
                s.shutdownInput();
                s.shutdownOutput();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
    
        public static byte[] readBytes(DataInputStream in,int length) throws IOException {
            int r=0;
            byte[] data=new byte[length];
            while(r<length){
                r+=in.read(data,r,length-r);
            }
    
            return data;
        }
    
        public static void writeBytes(DataOutputStream out,byte[] bytes,int length) throws IOException{
            out.writeInt(length);
            out.write(bytes,0,length);
            out.flush();
        }
    }
    



    展开全文
  • java实现https免证书认证   解决方法: 1.下载两个包,httpclient-4.2.jar和httpcore-4.2.jar,复制以下代码就可使用。 2.调用类代码:http://www.yayihouse.com/yayishuwu/chapter/1663...

    java实现https免证书认证

     

    解决方法:

    1.下载两个包,httpclient-4.2.jar和httpcore-4.2.jar,复制以下代码就可使用。

    2.调用类代码http://www.yayihouse.com/yayishuwu/chapter/1663

    展开全文
  • java实现https请求

    万次阅读 2018-08-07 21:25:45
    ...import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net....
  • Java实现https请求

    千次阅读 2019-01-23 19:06:08
    /** * @author XuJD * @create 2019-01-21 17:21 **/ public class HttpsUtil { private static Logger logger = LoggerFactory.getLogger(HttpsUtil.class);... public static JSONObject httpsRequest(St...
  • java实现https双向认证

    千次阅读 2017-11-14 00:39:05
    了解了一些https的工作原理,但是还是理解的不透彻,参考其他实现,写了一段代码练手。 参考文章: 1.讲https的工作原理的:Java 和 HTTP 的那些事(四) HTTPS 和 证书 2.keytool相关命令:使用keytool 生成证书 ...
  • java 实现https请求

    2015-04-01 17:29:24
    摘 要 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问。但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点。本文在简要介绍JSSE的基础上提出...
  • Java实现HTTPS通讯

    2014-11-01 21:34:32
    使用SSL会用到JSSE(Java Secure Socket Extension),JSSE对Java访问SSL和TLS协议都做了封装。 图 1. JSSE相关类之间的关系   安全套接字程序编写的方法 使用 Java 编写安全套接字程序,可以遵循一定...
  • java实现https协议

    千次阅读 2015-10-23 16:34:26
    import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import javax.net.ssl.SSLContext; import org.apache.http.HttpEntity; import org....
  • Java实现HTTPS加密、解密过程

    千次阅读 2017-02-07 23:13:40
    1.HTTPS握手过程模拟 以下文章来自:... 1.1准备工作  1、创建java证书:  C:\> keytool -genkey -alias wangyi -keypass wangyi -keyalg RSA -keysize 1024 -keystore https.keystore -sto
  • JAVA实现HTTPS接口(POST方式)

    万次阅读 2017-12-22 14:24:04
    前言:最近开发一个项目,需要回调其他公司的HTTPS...1.实现X509证书信任管理器类(避免导证书) import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java
  • HTTPS那些事 用java实现HTTPS工作原理

    万次阅读 2016-06-14 10:09:20
    今天被问到关于https原理的问题,结果由于知识掌握不牢靠,停留于表面,很多细节都无法回答清楚,于是决定把https的原理弄个明白,废话不多说,我们先看看https的定义  (由于很久未写博客,排版有些凌乱,请...
  • JAVA实现https单向认证

    万次阅读 2014-09-04 09:09:55
    Scheme sch = new Scheme("https", socketFactory, 443); httpClient.getConnectionManager().getSchemeRegistry().register(sch); } catch (Exception e) { e.printStackTrace(); } //下面这段是调用...
  • java实现https请求绕过证书检测

    千次阅读 2019-01-23 10:24:59
    import org.apache.http.HttpEntity; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.... imp...
  • java 实现https请求的基本原理与介绍

    万次阅读 2016-09-05 17:38:09
    摘 要 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问。但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点。本文在简要介绍JSSE的基础上...
  • JAVA实现HTTPS协议POST请求JSON报文

    万次阅读 2017-12-11 16:48:08
    HTTPS和HTTP的区别 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以...
  • String url = "https://api.r-guardian.com/product/batch/info"; //编码格式 try { String charset = "UTF-8"; //请求内容 ArrayList<String> list = new ArrayList(); list.add("xxx"); macAddress ...
  • * 证书信任管理器(用于https请求) * */ public class MyX509TrustManager implements X509TrustManager{ @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s...
  • java实现https ssl请求url

    千次阅读 2011-09-26 09:00:28
    import java.io.*; import java.net.*; import java.security.*; import java.security.cert.*; import java.util.*; import javax.net.ssl.*; publ

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,024
精华内容 9,209
关键字:

java实现https

java 订阅