溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

手摸手帶你認識https涉及的知識并實現(xiàn)通信

發(fā)布時間:2020-05-31 15:07:07 來源:網(wǎng)絡(luò) 閱讀:1501 作者:lgx211 欄目:編程語言

@[toc]
看完整的代碼,直接去完整代碼實現(xiàn),看實現(xiàn)完后會遇到的坑,直接去測試過程中的問題,包括經(jīng)過代理服務(wù)器訪問https,通過ip訪問https等。

http訪問流程

我們開發(fā)java web項目時,打好war包放到tomcat應(yīng)用服務(wù)器的webapps目錄下,tomcat的訪問端口是8080,啟動tomcat,在瀏覽器的地址欄輸入http://localhost:8080。就會看到如下
手摸手帶你認識https涉及的知識并實現(xiàn)通信

那么,看看服務(wù)器到底返回了什么內(nèi)容,在web項目中,運行代碼

package com.lgx.http;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class t1 {

    /*
    測試http請求服務(wù)器,看服務(wù)器返回了什么東西。
     */
    public static void main(String[] args) {
        try {
            URL url = new URL("http://localhost:8080");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            InputStream input = connection.getInputStream();
            // 默認的index.jsp頁面字節(jié)數(shù)遠遠小于1024
            byte[] bytes = new byte[1024];
            int bytesLength = input.read(bytes);
            System.out.println("服務(wù)器返回:\n" + new String(bytes, 0, bytesLength));
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

得到結(jié)果如下

手摸手帶你認識https涉及的知識并實現(xiàn)通信

上面其實并不是完整的服務(wù)器返回給瀏覽器的內(nèi)容,被我們輸出的只是http報文體,但這并不重要!可以看出數(shù)據(jù)并未加密。

https訪問流程

更改上述代碼,把URL的http改為https,會報錯。需要配置一下tomcat服務(wù)器

配置

tomcat配置支持https訪問,如果使用nginx還需配nginx。

創(chuàng)建密鑰庫

用Java自帶的keytool生成一個秘鑰庫

keytool -genkey -alias "tomcat" -keyalg "RSA" -keysize 1024 -validity 365 -keystore "/Users/liguoxi/Public/tomcat.keystore"

秘密設(shè)置為123456
手摸手帶你認識https涉及的知識并實現(xiàn)通信
注:KeyStore一般用JDK中的keytool生成。Keytool使用RSA或DSA KeyPairGenerator生成一個秘鑰對并連同新生成的證書一起存入KeyStore文件中。

修改XML文件

server.xml的Https配置默認是注釋掉的,干脆手動加上。

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
    maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS"
    keystoreFile="/Users/liguoxi/Public/tomcat.keystore"
    keystorePass="123456"/>

更改http訪問代碼為https訪問代碼,啟動項目,再以Java運行下述代碼。

package com.lgx.https;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.InputStream;
import java.net.URL;

public class t1 {
    public static void main(String[] args) {
        // 輸出https握手過程
        System.setProperty("javax.net.debug", "all");
        // 值配置成與tomcat keyStoreFile一致,服務(wù)器發(fā)過來的證書,要存在于信任秘鑰庫中
        System.setProperty("javax.net.ssl.trustStore", "/Users/liguoxi/Public/tomcat.keystore");
        // 信任秘鑰庫密碼
        System.setProperty("javax.net.ssl.trustStorePassword", "123456");
        // https協(xié)議版本
        System.setProperty("https.protocols", "TLSv1");
        try {
            URL url = new URL("https://localhost:8443");
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    // 證書里面有個擴展域,記錄了服務(wù)器ip,如果與訪問url里面的ip不一致不報錯
                    //其實是因為用keytool生成的證書,并沒有這個擴展域
                    return true;
                }
            });
            connection.connect();
            InputStream input = connection.getInputStream();
            byte[] bytes = new byte[1024];
            int bytesLength = input.read(bytes);
            System.out.println("服務(wù)器返回:\n" + new String(bytes, 0, bytesLength));
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

輸出一大堆

trustStore is: /Users/liguoxi/Public/tomcat.keystore
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=LGX, OU=LGX, O=LGX, L=LGX, ST=LGX, C=LGX
  Issuer:  CN=LGX, OU=LGX, O=LGX, L=LGX, ST=LGX, C=LGX
  Algorithm: RSA; Serial number: 0x21e45f2c
  Valid from Sun Oct 07 21:27:58 CST 2018 until Mon Oct 07 21:27:58 CST 2019

keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
trigger seeding of SecureRandom
done seeding SecureRandom
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(0) called
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1522146822 bytes = { 206, 221, 190, 215, 203, 75, 100, 29, 253, 204, 139, 195, 132, 250, 231, 86, 226, 225, 94, 88, 154, 174, 37, 73, 148, 29, 117, 165 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension extended_master_secret
***
[write] MD5 and SHA1 hashes:  len = 125
0000: 01 00 00 79 03 01 5B BA   1E 06 CE DD BE D7 CB 4B  ...y..[........K
0010: 64 1D FD CC 8B C3 84 FA   E7 56 E2 E1 5E 58 9A AE  d........V..^X..
0020: 25 49 94 1D 75 A5 00 00   2C C0 0A C0 14 00 35 C0  %I..u...,.....5.
0030: 05 C0 0F 00 39 00 38 C0   09 C0 13 00 2F C0 04 C0  ....9.8...../...
0040: 0E 00 33 00 32 C0 08 C0   12 00 0A C0 03 C0 0D 00  ..3.2...........
0050: 16 00 13 00 FF 01 00 00   24 00 0A 00 16 00 14 00  ........$.......
0060: 17 00 18 00 19 00 09 00   0A 00 0B 00 0C 00 0D 00  ................
0070: 0E 00 16 00 0B 00 02 01   00 00 17 00 00           .............
main, WRITE: TLSv1 Handshake, length = 125
[Raw write]: length = 130
0000: 16 03 01 00 7D 01 00 00   79 03 01 5B BA 1E 06 CE  ........y..[....
0010: DD BE D7 CB 4B 64 1D FD   CC 8B C3 84 FA E7 56 E2  ....Kd........V.
0020: E1 5E 58 9A AE 25 49 94   1D 75 A5 00 00 2C C0 0A  .^X..%I..u...,..
0030: C0 14 00 35 C0 05 C0 0F   00 39 00 38 C0 09 C0 13  ...5.....9.8....
0040: 00 2F C0 04 C0 0E 00 33   00 32 C0 08 C0 12 00 0A  ./.....3.2......
0050: C0 03 C0 0D 00 16 00 13   00 FF 01 00 00 24 00 0A  .............$..
0060: 00 16 00 14 00 17 00 18   00 19 00 09 00 0A 00 0B  ................
0070: 00 0C 00 0D 00 0E 00 16   00 0B 00 02 01 00 00 17  ................
0080: 00 00                                              ..
[Raw read]: length = 5
0000: 16 03 01 03 74                                     ....t
[Raw read]: length = 884
0000: 02 00 00 51 03 01 5B BA   1E 06 88 96 19 DB 9A CF  ...Q..[.........
0010: 95 E3 75 CB 71 6F 48 8E   06 80 97 2A 74 AE D2 D1  ..u.qoH....*t...
0020: 16 84 AA 11 C5 A9 20 5B   BA 1E 06 D6 62 98 69 C8  ...... [....b.i.
0030: 8C 1E 30 F0 DA B6 5D B6   C8 6E 35 D1 A0 D0 83 0B  ..0...]..n5.....
0040: F7 FB 3A D5 A1 65 3C C0   14 00 00 09 FF 01 00 01  ..:..e<.........
0050: 00 00 17 00 00 0B 00 02   4C 00 02 49 00 02 46 30  ........L..I..F0
0060: 82 02 42 30 82 01 AB A0   03 02 01 02 02 04 21 E4  ..B0..........!.
0070: 5F 2C 30 0D 06 09 2A 86   48 86 F7 0D 01 01 0B 05  _,0...*.H.......
0080: 00 30 54 31 0C 30 0A 06   03 55 04 06 13 03 4C 47  .0T1.0...U....LG
0090: 58 31 0C 30 0A 06 03 55   04 08 13 03 4C 47 58 31  X1.0...U....LGX1
00A0: 0C 30 0A 06 03 55 04 07   13 03 4C 47 58 31 0C 30  .0...U....LGX1.0
00B0: 0A 06 03 55 04 0A 13 03   4C 47 58 31 0C 30 0A 06  ...U....LGX1.0..
00C0: 03 55 04 0B 13 03 4C 47   58 31 0C 30 0A 06 03 55  .U....LGX1.0...U
00D0: 04 03 13 03 4C 47 58 30   1E 17 0D 31 38 31 30 30  ....LGX0...18100
00E0: 37 31 33 32 37 35 38 5A   17 0D 31 39 31 30 30 37  7132758Z..191007
00F0: 31 33 32 37 35 38 5A 30   54 31 0C 30 0A 06 03 55  132758Z0T1.0...U
0100: 04 06 13 03 4C 47 58 31   0C 30 0A 06 03 55 04 08  ....LGX1.0...U..
0110: 13 03 4C 47 58 31 0C 30   0A 06 03 55 04 07 13 03  ..LGX1.0...U....
0120: 4C 47 58 31 0C 30 0A 06   03 55 04 0A 13 03 4C 47  LGX1.0...U....LG
0130: 58 31 0C 30 0A 06 03 55   04 0B 13 03 4C 47 58 31  X1.0...U....LGX1
0140: 0C 30 0A 06 03 55 04 03   13 03 4C 47 58 30 81 9F  .0...U....LGX0..
0150: 30 0D 06 09 2A 86 48 86   F7 0D 01 01 01 05 00 03  0...*.H.........
0160: 81 8D 00 30 81 89 02 81   81 00 9C 61 24 6E EC D3  ...0.......a$n..
0170: A1 6B 6A 12 36 D6 CB 03   9A 9B 6C 9F A7 C6 B8 FD  .kj.6.....l.....
0180: 19 5D 91 F8 16 EB D5 06   7E A6 1E 09 DB 1F EA 95  .]..............
0190: F3 3A 73 21 DA A5 B6 BD   2A 46 40 20 BD 6E 55 83  .:s!....*F@ .nU.
01A0: 42 86 F7 8E 5B 84 C7 45   0E 02 F8 76 75 DE 41 FD  B...[..E...vu.A.
01B0: 6D B6 A7 50 09 04 71 0D   A8 AA F4 73 59 2C C0 36  m..P..q....sY,.6
01C0: 5C 68 2E BA 99 43 2D DF   C0 4D 70 66 EC 93 08 D7  \h...C-..Mpf....
01D0: 05 0D 75 5A C3 0D 04 CC   18 F9 5D E5 73 E4 E9 14  ..uZ......].s...
01E0: 53 5D D5 0C 6F 16 E4 2C   AE 47 02 03 01 00 01 A3  S]..o..,.G......
01F0: 21 30 1F 30 1D 06 03 55   1D 0E 04 16 04 14 E0 A4  !0.0...U........
0200: 47 46 87 0B 8D 4F A6 B2   29 57 D7 1D 59 78 02 F1  GF...O..)W..Yx..
0210: D8 2B 30 0D 06 09 2A 86   48 86 F7 0D 01 01 0B 05  .+0...*.H.......
0220: 00 03 81 81 00 4D 14 33   08 83 64 F8 90 E5 27 AA  .....M.3..d...'.
0230: CC FC 54 1C 20 B9 84 A6   D0 53 47 F1 98 F7 CF 20  ..T. ....SG.... 
0240: D7 81 34 12 84 2E 0F E2   A9 2D 26 21 4B E0 EA A6  ..4......-&!K...
0250: F4 57 87 AB EF CB C8 86   A1 D3 29 80 CA 49 9F EF  .W........)..I..
0260: 61 BF BB F6 62 0F 15 EF   5C 19 F2 D7 C7 5E DC F3  a...b...\....^..
0270: FD F6 A1 F3 30 69 DA F9   AA 4C 7C CC DE 8F B2 D6  ....0i...L......
0280: 96 43 72 BC B9 F7 00 25   43 37 8B E0 8A A7 76 CF  .Cr....%C7....v.
0290: 9B E8 54 E8 C9 F6 33 4E   8F 8C F7 C8 DF 37 20 67  ..T...3N.....7 g
02A0: 50 C6 A3 19 42 0C 00 00   C7 03 00 17 41 04 83 ED  P...B.......A...
02B0: F0 6A BA DC AD 5E 46 5C   F7 F6 28 AA E2 0E 97 A2  .j...^F\..(.....
02C0: CA 41 A9 51 10 E9 AA EA   F4 7A 9D 62 2B B8 31 72  .A.Q.....z.b+.1r
02D0: D6 33 03 D0 96 59 23 64   38 B7 D2 0E 70 E7 3C 5C  .3...Y#d8...p.<\
02E0: C1 EC A1 51 97 18 33 1F   AD 42 69 9D AE B9 00 80  ...Q..3..Bi.....
02F0: 79 79 70 2C 31 D3 DC 28   D5 0C C0 37 23 E1 71 FC  yyp,1..(...7#.q.
0300: A1 96 2F C8 8A 35 5E 95   EB EF 13 27 C3 52 8A A7  ../..5^....'.R..
0310: 50 70 AF EC ED E6 B9 F6   05 18 52 40 23 5D 63 CC  Pp........R@#]c.
0320: E2 89 92 00 26 A5 41 7B   13 F2 D2 8C 31 3C 23 41  ....&.A.....1<#A
0330: 6F 4E 1B 8A 9A 35 0E 0B   F6 AE 8D 86 4B D6 3E A2  oN...5......K.>.
0340: 79 EB 61 B6 47 B0 42 B5   6E 85 09 23 84 46 46 99  y.a.G.B.n..#.FF.
0350: 81 CD C8 23 8B 2C 26 32   1B C0 03 FC 9B 8B 14 D1  ...#.,&2........
0360: F6 E1 89 4A EA ED EF C4   6D E9 E5 86 22 E4 8E 7C  ...J....m..."...
0370: 0E 00 00 00                                        ....
main, READ: TLSv1 Handshake, length = 884
*** ServerHello, TLSv1
RandomCookie:  GMT: 1522146822 bytes = { 136, 150, 25, 219, 154, 207, 149, 227, 117, 203, 113, 111, 72, 142, 6, 128, 151, 42, 116, 174, 210, 209, 22, 132, 170, 17, 197, 169 }
Session ID:  {91, 186, 30, 6, 214, 98, 152, 105, 200, 140, 30, 48, 240, 218, 182, 93, 182, 200, 110, 53, 209, 160, 208, 131, 11, 247, 251, 58, 213, 161, 101, 60}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
Extension extended_master_secret
***
%% Initialized:  [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]
** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[read] MD5 and SHA1 hashes:  len = 85
0000: 02 00 00 51 03 01 5B BA   1E 06 88 96 19 DB 9A CF  ...Q..[.........
0010: 95 E3 75 CB 71 6F 48 8E   06 80 97 2A 74 AE D2 D1  ..u.qoH....*t...
0020: 16 84 AA 11 C5 A9 20 5B   BA 1E 06 D6 62 98 69 C8  ...... [....b.i.
0030: 8C 1E 30 F0 DA B6 5D B6   C8 6E 35 D1 A0 D0 83 0B  ..0...]..n5.....
0040: F7 FB 3A D5 A1 65 3C C0   14 00 00 09 FF 01 00 01  ..:..e<.........
0050: 00 00 17 00 00                                     .....
*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: CN=LGX, OU=LGX, O=LGX, L=LGX, ST=LGX, C=LGX
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 1024 bits
  modulus: 109813392808966985140540821321555924175057214027222884095960986513876498186792795206052237836949373963973650543086709232968823011726525283075591130943590026095316290548201219746527439812794723752498763782639568103955938705793191742259325257069819861478415993347120306343465466402849805688743066088416645787207
  public exponent: 65537
  Validity: [From: Sun Oct 07 21:27:58 CST 2018,
               To: Mon Oct 07 21:27:58 CST 2019]
  Issuer: CN=LGX, OU=LGX, O=LGX, L=LGX, ST=LGX, C=LGX
  SerialNumber: [    21e45f2c]

Certificate Extensions: 1
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: E0 A4 47 46 87 0B 8D 4F   A6 B2 29 57 D7 1D 59 78  ..GF...O..)W..Yx
0010: 02 F1 D8 2B                                        ...+
]
]

]
  Algorithm: [SHA256withRSA]
  Signature:
0000: 4D 14 33 08 83 64 F8 90   E5 27 AA CC FC 54 1C 20  M.3..d...'...T. 
0010: B9 84 A6 D0 53 47 F1 98   F7 CF 20 D7 81 34 12 84  ....SG.... ..4..
0020: 2E 0F E2 A9 2D 26 21 4B   E0 EA A6 F4 57 87 AB EF  ....-&!K....W...
0030: CB C8 86 A1 D3 29 80 CA   49 9F EF 61 BF BB F6 62  .....)..I..a...b
0040: 0F 15 EF 5C 19 F2 D7 C7   5E DC F3 FD F6 A1 F3 30  ...\....^......0
0050: 69 DA F9 AA 4C 7C CC DE   8F B2 D6 96 43 72 BC B9  i...L.......Cr..
0060: F7 00 25 43 37 8B E0 8A   A7 76 CF 9B E8 54 E8 C9  ..%C7....v...T..
0070: F6 33 4E 8F 8C F7 C8 DF   37 20 67 50 C6 A3 19 42  .3N.....7 gP...B

]
***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=LGX, OU=LGX, O=LGX, L=LGX, ST=LGX, C=LGX
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 1024 bits
  modulus: 109813392808966985140540821321555924175057214027222884095960986513876498186792795206052237836949373963973650543086709232968823011726525283075591130943590026095316290548201219746527439812794723752498763782639568103955938705793191742259325257069819861478415993347120306343465466402849805688743066088416645787207
  public exponent: 65537
  Validity: [From: Sun Oct 07 21:27:58 CST 2018,
               To: Mon Oct 07 21:27:58 CST 2019]
  Issuer: CN=LGX, OU=LGX, O=LGX, L=LGX, ST=LGX, C=LGX
  SerialNumber: [    21e45f2c]

Certificate Extensions: 1
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: E0 A4 47 46 87 0B 8D 4F   A6 B2 29 57 D7 1D 59 78  ..GF...O..)W..Yx
0010: 02 F1 D8 2B                                        ...+
]
]

]
  Algorithm: [SHA256withRSA]
  Signature:
0000: 4D 14 33 08 83 64 F8 90   E5 27 AA CC FC 54 1C 20  M.3..d...'...T. 
0010: B9 84 A6 D0 53 47 F1 98   F7 CF 20 D7 81 34 12 84  ....SG.... ..4..
0020: 2E 0F E2 A9 2D 26 21 4B   E0 EA A6 F4 57 87 AB EF  ....-&!K....W...
0030: CB C8 86 A1 D3 29 80 CA   49 9F EF 61 BF BB F6 62  .....)..I..a...b
0040: 0F 15 EF 5C 19 F2 D7 C7   5E DC F3 FD F6 A1 F3 30  ...\....^......0
0050: 69 DA F9 AA 4C 7C CC DE   8F B2 D6 96 43 72 BC B9  i...L.......Cr..
0060: F7 00 25 43 37 8B E0 8A   A7 76 CF 9B E8 54 E8 C9  ..%C7....v...T..
0070: F6 33 4E 8F 8C F7 C8 DF   37 20 67 50 C6 A3 19 42  .3N.....7 gP...B

]
[read] MD5 and SHA1 hashes:  len = 592
0000: 0B 00 02 4C 00 02 49 00   02 46 30 82 02 42 30 82  ...L..I..F0..B0.
0010: 01 AB A0 03 02 01 02 02   04 21 E4 5F 2C 30 0D 06  .........!._,0..
0020: 09 2A 86 48 86 F7 0D 01   01 0B 05 00 30 54 31 0C  .*.H........0T1.
0030: 30 0A 06 03 55 04 06 13   03 4C 47 58 31 0C 30 0A  0...U....LGX1.0.
0040: 06 03 55 04 08 13 03 4C   47 58 31 0C 30 0A 06 03  ..U....LGX1.0...
0050: 55 04 07 13 03 4C 47 58   31 0C 30 0A 06 03 55 04  U....LGX1.0...U.
0060: 0A 13 03 4C 47 58 31 0C   30 0A 06 03 55 04 0B 13  ...LGX1.0...U...
0070: 03 4C 47 58 31 0C 30 0A   06 03 55 04 03 13 03 4C  .LGX1.0...U....L
0080: 47 58 30 1E 17 0D 31 38   31 30 30 37 31 33 32 37  GX0...1810071327
0090: 35 38 5A 17 0D 31 39 31   30 30 37 31 33 32 37 35  58Z..19100713275
00A0: 38 5A 30 54 31 0C 30 0A   06 03 55 04 06 13 03 4C  8Z0T1.0...U....L
00B0: 47 58 31 0C 30 0A 06 03   55 04 08 13 03 4C 47 58  GX1.0...U....LGX
00C0: 31 0C 30 0A 06 03 55 04   07 13 03 4C 47 58 31 0C  1.0...U....LGX1.
00D0: 30 0A 06 03 55 04 0A 13   03 4C 47 58 31 0C 30 0A  0...U....LGX1.0.
00E0: 06 03 55 04 0B 13 03 4C   47 58 31 0C 30 0A 06 03  ..U....LGX1.0...
00F0: 55 04 03 13 03 4C 47 58   30 81 9F 30 0D 06 09 2A  U....LGX0..0...*
0100: 86 48 86 F7 0D 01 01 01   05 00 03 81 8D 00 30 81  .H............0.
0110: 89 02 81 81 00 9C 61 24   6E EC D3 A1 6B 6A 12 36  ......a$n...kj.6
0120: D6 CB 03 9A 9B 6C 9F A7   C6 B8 FD 19 5D 91 F8 16  .....l......]...
0130: EB D5 06 7E A6 1E 09 DB   1F EA 95 F3 3A 73 21 DA  ............:s!.
0140: A5 B6 BD 2A 46 40 20 BD   6E 55 83 42 86 F7 8E 5B  ...*F@ .nU.B...[
0150: 84 C7 45 0E 02 F8 76 75   DE 41 FD 6D B6 A7 50 09  ..E...vu.A.m..P.
0160: 04 71 0D A8 AA F4 73 59   2C C0 36 5C 68 2E BA 99  .q....sY,.6\h...
0170: 43 2D DF C0 4D 70 66 EC   93 08 D7 05 0D 75 5A C3  C-..Mpf......uZ.
0180: 0D 04 CC 18 F9 5D E5 73   E4 E9 14 53 5D D5 0C 6F  .....].s...S]..o
0190: 16 E4 2C AE 47 02 03 01   00 01 A3 21 30 1F 30 1D  ..,.G......!0.0.
01A0: 06 03 55 1D 0E 04 16 04   14 E0 A4 47 46 87 0B 8D  ..U........GF...
01B0: 4F A6 B2 29 57 D7 1D 59   78 02 F1 D8 2B 30 0D 06  O..)W..Yx...+0..
01C0: 09 2A 86 48 86 F7 0D 01   01 0B 05 00 03 81 81 00  .*.H............
01D0: 4D 14 33 08 83 64 F8 90   E5 27 AA CC FC 54 1C 20  M.3..d...'...T. 
01E0: B9 84 A6 D0 53 47 F1 98   F7 CF 20 D7 81 34 12 84  ....SG.... ..4..
01F0: 2E 0F E2 A9 2D 26 21 4B   E0 EA A6 F4 57 87 AB EF  ....-&!K....W...
0200: CB C8 86 A1 D3 29 80 CA   49 9F EF 61 BF BB F6 62  .....)..I..a...b
0210: 0F 15 EF 5C 19 F2 D7 C7   5E DC F3 FD F6 A1 F3 30  ...\....^......0
0220: 69 DA F9 AA 4C 7C CC DE   8F B2 D6 96 43 72 BC B9  i...L.......Cr..
0230: F7 00 25 43 37 8B E0 8A   A7 76 CF 9B E8 54 E8 C9  ..%C7....v...T..
0240: F6 33 4E 8F 8C F7 C8 DF   37 20 67 50 C6 A3 19 42  .3N.....7 gP...B
*** ECDH ServerKeyExchange
Server key: Sun EC public key, 256 bits
  public x coord: 59673385215316818009352331687060949082651775895246442016413736342443150945208
  public y coord: 22366228495042026761421384723174683132027538974986677415966731768560927747769
  parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
[read] MD5 and SHA1 hashes:  len = 203
0000: 0C 00 00 C7 03 00 17 41   04 83 ED F0 6A BA DC AD  .......A....j...
0010: 5E 46 5C F7 F6 28 AA E2   0E 97 A2 CA 41 A9 51 10  ^F\..(......A.Q.
0020: E9 AA EA F4 7A 9D 62 2B   B8 31 72 D6 33 03 D0 96  ....z.b+.1r.3...
0030: 59 23 64 38 B7 D2 0E 70   E7 3C 5C C1 EC A1 51 97  Y#d8...p.<\...Q.
0040: 18 33 1F AD 42 69 9D AE   B9 00 80 79 79 70 2C 31  .3..Bi.....yyp,1
0050: D3 DC 28 D5 0C C0 37 23   E1 71 FC A1 96 2F C8 8A  ..(...7#.q.../..
0060: 35 5E 95 EB EF 13 27 C3   52 8A A7 50 70 AF EC ED  5^....'.R..Pp...
0070: E6 B9 F6 05 18 52 40 23   5D 63 CC E2 89 92 00 26  .....R@#]c.....&
0080: A5 41 7B 13 F2 D2 8C 31   3C 23 41 6F 4E 1B 8A 9A  .A.....1<#AoN...
0090: 35 0E 0B F6 AE 8D 86 4B   D6 3E A2 79 EB 61 B6 47  5......K.>.y.a.G
00A0: B0 42 B5 6E 85 09 23 84   46 46 99 81 CD C8 23 8B  .B.n..#.FF....#.
00B0: 2C 26 32 1B C0 03 FC 9B   8B 14 D1 F6 E1 89 4A EA  ,&2...........J.
00C0: ED EF C4 6D E9 E5 86 22   E4 8E 7C                 ...m..."...
*** ServerHelloDone
[read] MD5 and SHA1 hashes:  len = 4
0000: 0E 00 00 00                                        ....
*** ECDHClientKeyExchange
ECDH Public value:  { 4, 35, 76, 86, 107, 199, 33, 33, 214, 183, 130, 57, 64, 134, 252, 21, 63, 200, 236, 32, 109, 23, 243, 240, 10, 61, 76, 202, 241, 148, 221, 202, 125, 230, 205, 242, 124, 82, 195, 105, 131, 22, 78, 6, 228, 114, 175, 180, 24, 189, 93, 115, 105, 58, 23, 254, 214, 154, 27, 212, 119, 62, 228, 246, 89 }
[write] MD5 and SHA1 hashes:  len = 70
0000: 10 00 00 42 41 04 23 4C   56 6B C7 21 21 D6 B7 82  ...BA.#LVk.!!...
0010: 39 40 86 FC 15 3F C8 EC   20 6D 17 F3 F0 0A 3D 4C  9@...?.. m....=L
0020: CA F1 94 DD CA 7D E6 CD   F2 7C 52 C3 69 83 16 4E  ..........R.i..N
0030: 06 E4 72 AF B4 18 BD 5D   73 69 3A 17 FE D6 9A 1B  ..r....]si:.....
0040: D4 77 3E E4 F6 59                                  .w>..Y
main, WRITE: TLSv1 Handshake, length = 70
[Raw write]: length = 75
0000: 16 03 01 00 46 10 00 00   42 41 04 23 4C 56 6B C7  ....F...BA.#LVk.
0010: 21 21 D6 B7 82 39 40 86   FC 15 3F C8 EC 20 6D 17  !!...9@...?.. m.
0020: F3 F0 0A 3D 4C CA F1 94   DD CA 7D E6 CD F2 7C 52  ...=L..........R
0030: C3 69 83 16 4E 06 E4 72   AF B4 18 BD 5D 73 69 3A  .i..N..r....]si:
0040: 17 FE D6 9A 1B D4 77 3E   E4 F6 59                 ......w>..Y
SESSION KEYGEN:
PreMaster Secret:
0000: 08 C3 67 71 5C 60 68 86   44 12 4E F2 AB A1 6C 9A  ..gq\`h.D.N...l.
0010: 16 19 BA A0 D6 B6 AA 87   E1 F8 01 6F 43 05 72 74  ...........oC.rt
CONNECTION KEYGEN:
Client Nonce:
0000: 5B BA 1E 06 CE DD BE D7   CB 4B 64 1D FD CC 8B C3  [........Kd.....
0010: 84 FA E7 56 E2 E1 5E 58   9A AE 25 49 94 1D 75 A5  ...V..^X..%I..u.
Server Nonce:
0000: 5B BA 1E 06 88 96 19 DB   9A CF 95 E3 75 CB 71 6F  [...........u.qo
0010: 48 8E 06 80 97 2A 74 AE   D2 D1 16 84 AA 11 C5 A9  H....*t.........
Master Secret:
0000: 2A E2 CE B4 07 60 8D D2   16 AF 42 3C 97 30 12 BD  *....`....B<.0..
0010: 5D 04 AB 45 D4 61 F2 40   C2 ED 8F 6C 76 28 62 13  ]..E.a.@...lv(b.
0020: 14 23 D2 C3 40 37 26 AD   FC 9D 6C 07 1D AE CE D5  .#..@7&...l.....
Client MAC write Secret:
0000: 63 9F 1D 65 B3 F0 E2 CD   7B B1 A5 0D A6 3D E0 B9  c..e.........=..
0010: 34 A8 67 F7                                        4.g.
Server MAC write Secret:
0000: 92 50 43 14 8D E1 19 13   6B 1E 74 2C 70 5C 39 41  .PC.....k.t,p\9A
0010: 07 99 B9 46                                        ...F
Client write key:
0000: 98 97 3F AB 26 3A 14 D8   08 FC 26 C1 7E 07 2A C7  ..?.&:....&...*.
0010: 46 CC 21 03 0B 0F 87 4D   C9 27 79 19 0F C4 B8 7D  F.!....M.'y.....
Server write key:
0000: 50 20 AE 79 47 E8 BE 3C   79 06 0E 19 2E 3C F3 9A  P .yG..<y....<..
0010: 5F B0 33 57 2D 29 E4 70   15 7F 68 17 B8 21 18 E6  _.3W-).p..h..!..
Client write IV:
0000: FB 18 D1 8D D8 EA 8D 82   96 EB 9E 84 97 98 2D C4  ..............-.
Server write IV:
0000: 23 E6 E9 B6 DF 6C 0F 75   00 6A 01 AE 2F 8C D9 E1  #....l.u.j../...
main, WRITE: TLSv1 Change Cipher Spec, length = 1
[Raw write]: length = 6
0000: 14 03 01 00 01 01                                  ......
*** Finished
verify_data:  { 138, 44, 121, 7, 61, 112, 195, 10, 93, 222, 35, 164 }
***
[write] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C 8A 2C 79 07   3D 70 C3 0A 5D DE 23 A4  .....,y.=p..].#.
Padded plaintext before ENCRYPTION:  len = 48
0000: 14 00 00 0C 8A 2C 79 07   3D 70 C3 0A 5D DE 23 A4  .....,y.=p..].#.
0010: C6 E4 F7 C2 32 85 2B 30   18 1A F8 4B 5E 29 22 BE  ....2.+0...K^)".
0020: 5E 15 71 A1 0B 0B 0B 0B   0B 0B 0B 0B 0B 0B 0B 0B  ^.q.............
main, WRITE: TLSv1 Handshake, length = 48
[Raw write]: length = 53
0000: 16 03 01 00 30 91 87 EB   A3 09 E8 AC 17 7A 33 A3  ....0........z3.
0010: 0B 42 22 02 92 18 D7 52   1A 49 DA 0E 3C 11 D4 EB  .B"....R.I..<...
0020: 6D 19 F2 D6 01 A0 29 18   93 20 7C 3B CF A0 BC E0  m.....).. .;....
0030: A9 41 17 1B E7                                     .A...
[Raw read]: length = 5
0000: 14 03 01 00 01                                     .....
[Raw read]: length = 1
0000: 01                                                 .
main, READ: TLSv1 Change Cipher Spec, length = 1
[Raw read]: length = 5
0000: 16 03 01 00 30                                     ....0
[Raw read]: length = 48
0000: 77 16 6B 89 41 7E 3F 93   DA 66 F5 DF EF 6F 90 A8  w.k.A.?..f...o..
0010: 1B 51 DD 97 AC 11 A4 66   B5 2C A3 69 A4 5A 92 3A  .Q.....f.,.i.Z.:
0020: C1 52 09 3E 20 01 BB 2C   55 BE 2E 52 93 63 B6 ED  .R.> ..,U..R.c..
main, READ: TLSv1 Handshake, length = 48
Padded plaintext after DECRYPTION:  len = 48
0000: 14 00 00 0C C0 1E 82 40   64 A8 15 62 8D DC A0 62  .......@d..b...b
0010: 0B B4 25 EF 31 D1 F9 5C   FD DE 87 E9 CE 69 BB EB  ..%.1..\.....i..
0020: C0 C3 F3 BD 0B 0B 0B 0B   0B 0B 0B 0B 0B 0B 0B 0B  ................
*** Finished
verify_data:  { 192, 30, 130, 64, 100, 168, 21, 98, 141, 220, 160, 98 }
***
%% Cached client session: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]
[read] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C C0 1E 82 40   64 A8 15 62 8D DC A0 62  .......@d..b...b
Padded plaintext before ENCRYPTION:  len = 176
0000: 47 45 54 20 2F 20 48 54   54 50 2F 31 2E 31 0D 0A  GET / HTTP/1.1..
0010: 55 73 65 72 2D 41 67 65   6E 74 3A 20 4A 61 76 61  User-Agent: Java
0020: 2F 31 2E 38 2E 30 5F 31   36 31 0D 0A 48 6F 73 74  /1.8.0_161..Host
0030: 3A 20 6C 6F 63 61 6C 68   6F 73 74 3A 38 34 34 33  : localhost:8443
0040: 0D 0A 41 63 63 65 70 74   3A 20 74 65 78 74 2F 68  ..Accept: text/h
0050: 74 6D 6C 2C 20 69 6D 61   67 65 2F 67 69 66 2C 20  tml, image/gif, 
0060: 69 6D 61 67 65 2F 6A 70   65 67 2C 20 2A 3B 20 71  image/jpeg, *; q
0070: 3D 2E 32 2C 20 2A 2F 2A   3B 20 71 3D 2E 32 0D 0A  =.2, */*; q=.2..
0080: 43 6F 6E 6E 65 63 74 69   6F 6E 3A 20 6B 65 65 70  Connection: keep
0090: 2D 61 6C 69 76 65 0D 0A   0D 0A 1F DF A2 19 1D E1  -alive..........
00A0: 23 86 92 33 C1 11 02 95   1E 95 1F 6D E4 CB 01 01  #..3.......m....
main, WRITE: TLSv1 Application Data, length = 176
[Raw write]: length = 181
0000: 17 03 01 00 B0 0D 7D 68   DD 5B 28 FE 81 9F 15 25  .......h.[(....%
0010: D5 37 68 3D E1 77 7E 87   1D 24 32 9A F6 58 D4 B4  .7h=.w...$2..X..
0020: A9 95 38 70 31 7A 49 3F   20 B8 B2 85 9E 11 C0 1F  ..8p1zI? .......
0030: 96 20 A5 B0 39 80 09 AA   87 DE 35 B4 D3 98 01 6C  . ..9.....5....l
0040: 39 9A 3B 14 A0 CD E7 D4   B4 AA C7 8A C6 E1 AC DA  9.;.............
0050: 92 4A 49 D4 F7 E7 B6 4F   82 1B D2 F5 D8 B8 18 D3  .JI....O........
0060: 96 A5 EA A8 1C A3 30 04   C7 A4 EE 98 0F A2 6F E8  ......0.......o.
0070: DC AF F7 E5 9A 6E 0A 8B   BD E4 06 AD 65 FC 8D 2E  .....n......e...
0080: F2 D3 E5 C0 3F F1 C0 83   F0 07 09 58 34 7D F9 D9  ....?......X4...
0090: E7 AB EF 2F D0 E0 86 43   A2 DF FD 0D 1F A6 39 09  .../...C......9.
00A0: BB FD 5C 5D 65 D6 25 C1   AE F8 B4 9F 5C 8D D6 EA  ..\]e.%.....\...
00B0: 63 1A 40 1B B8                                     c.@..
[Raw read]: length = 5
0000: 17 03 01 01 40                                     ....@
[Raw read]: length = 320
0000: B0 AA 6A 6E F6 37 D3 C6   66 BB 17 A7 27 F3 3C 74  ..jn.7..f...'.<t
0010: 6A DF 16 C5 9E F8 34 BB   B6 8E FA FE 6E 52 F4 39  j.....4.....nR.9
0020: 5B 88 5F 0A 91 76 C7 8B   62 E2 65 B7 EF 28 B6 8E  [._..v..b.e..(..
0030: FC 43 83 9E C8 A5 89 31   19 E0 E8 AE C3 EA C4 D8  .C.....1........
0040: 7A 54 68 62 88 35 D5 FB   4B 85 38 03 EC A1 DC 69  zThb.5..K.8....i
0050: 88 1C F8 E6 82 AC CD A3   E6 A9 7C 45 E4 12 47 FD  ...........E..G.
0060: 45 FA 66 D2 F0 D5 FE E2   7E 1C AF B4 35 C3 1C 77  E.f.........5..w
0070: C1 96 59 27 2D 98 8D AC   29 9F D4 8B 65 B3 4C 1B  ..Y'-...)...e.L.
0080: 34 B0 ED E6 DC 6B 73 A7   30 1A A6 A2 65 69 12 DA  4....ks.0...ei..
0090: FE B7 68 A4 E8 13 70 5C   5D 9E 8D 01 CA 68 DD 5F  ..h...p\]....h._
00A0: 57 DD 1D 46 40 9A CE B9   39 F4 EA C0 D5 B6 FC 6D  W..F@...9......m
00B0: 22 04 95 F7 7A 68 FA 84   0B B8 CE F1 B5 3B 09 6F  "...zh.......;.o
00C0: A8 DF 7C C7 0B A7 D7 68   17 EF F3 57 5D 01 D5 54  .......h...W]..T
00D0: D1 05 8E 69 AA 68 CB 75   9F A7 45 2E 7B 0B 9A 5A  ...i.h.u..E....Z
00E0: DB 64 29 BA 4C A9 9A 75   A2 56 53 6A D6 1F 63 27  .d).L..u.VSj..c'
00F0: A6 EA 03 AD 52 87 1D F4   8A D1 79 2F F0 96 8E 8C  ....R.....y/....
0100: A4 83 A1 32 77 5B A4 A0   27 28 2A BB 07 26 5C FF  ...2w[..'(*..&\.
0110: 5D 34 D8 F4 62 6F 4E CE   26 A5 A2 DE F3 89 06 A3  ]4..boN.&.......
0120: 71 85 71 41 23 D3 65 B8   8A 0B 5B DC 1E 24 C4 6C  q.qA#.e...[..$.l
0130: 2B B7 AC 18 91 87 62 E0   C0 A9 F5 3F 66 D5 4B E9  +.....b....?f.K.
main, READ: TLSv1 Application Data, length = 320
Padded plaintext after DECRYPTION:  len = 320
0000: 48 54 54 50 2F 31 2E 31   20 32 30 30 20 0D 0A 53  HTTP/1.1 200 ..S
0010: 65 74 2D 43 6F 6F 6B 69   65 3A 20 4A 53 45 53 53  et-Cookie: JSESS
0020: 49 4F 4E 49 44 3D 35 38   35 38 35 45 35 44 44 42  IONID=58585E5DDB
0030: 32 46 41 43 39 33 44 37   30 43 30 31 32 43 34 33  2FAC93D70C012C43
0040: 35 30 39 36 36 41 3B 20   50 61 74 68 3D 2F 3B 20  50966A; Path=/; 
0050: 53 65 63 75 72 65 3B 20   48 74 74 70 4F 6E 6C 79  Secure; HttpOnly
0060: 0D 0A 43 6F 6E 74 65 6E   74 2D 54 79 70 65 3A 20  ..Content-Type: 
0070: 74 65 78 74 2F 68 74 6D   6C 3B 63 68 61 72 73 65  text/html;charse
0080: 74 3D 55 54 46 2D 38 0D   0A 43 6F 6E 74 65 6E 74  t=UTF-8..Content
0090: 2D 4C 65 6E 67 74 68 3A   20 39 30 0D 0A 44 61 74  -Length: 90..Dat
00A0: 65 3A 20 53 75 6E 2C 20   30 37 20 4F 63 74 20 32  e: Sun, 07 Oct 2
00B0: 30 31 38 20 31 34 3A 35   33 3A 35 38 20 47 4D 54  018 14:53:58 GMT
00C0: 0D 0A 0D 0A 0A 0A 3C 68   74 6D 6C 3E 0A 20 20 3C  ......<html>.  <
00D0: 68 65 61 64 3E 0A 20 20   20 20 3C 74 69 74 6C 65  head>.    <title
00E0: 3E 24 54 69 74 6C 65 24   3C 2F 74 69 74 6C 65 3E  >$Title$</title>
00F0: 0A 20 20 3C 2F 68 65 61   64 3E 0A 20 20 3C 62 6F  .  </head>.  <bo
0100: 64 79 3E 0A 20 20 24 45   4E 44 24 0A 20 20 3C 2F  dy>.  $END$.  </
0110: 62 6F 64 79 3E 0A 3C 2F   68 74 6D 6C 3E 0A BE 57  body>.</html>..W
0120: 3B 52 9A FF 6D BC FF 62   7F 2E E1 D3 09 6E 28 6E  ;R..m..b.....n(n
0130: 1D 5A 0D 0D 0D 0D 0D 0D   0D 0D 0D 0D 0D 0D 0D 0D  .Z..............
服務(wù)器返回:

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  $END$
  </body>
</html>

main, called close()
main, called closeInternal(true)
main, SEND TLSv1 ALERT:  warning, description = close_notify
Padded plaintext before ENCRYPTION:  len = 32
0000: 01 00 CD B8 E3 0A D9 66   F4 9C 87 B8 66 33 CD C2  .......f....f3..
0010: E3 35 56 B3 29 7E 09 09   09 09 09 09 09 09 09 09  .5V.)...........
main, WRITE: TLSv1 Alert, length = 32
[Raw write]: length = 37
0000: 15 03 01 00 20 CC D0 CF   38 5B EF CF A9 F3 BB 94  .... ...8[......
0010: 0D BA 81 EC 25 83 7A 70   83 EE C7 4E CE 46 89 6A  ....%.zp...N.F.j
0020: 3E 10 46 0C FD                                     >.F..
main, called closeSocket(true)

Process finished with exit code 0
流程概述

什么意思?

[Raw write]和[Raw read],我們和tomcat服務(wù)器之間建立socket連接之后,Raw write是我們寫給服務(wù)器的字節(jié)內(nèi)容,Raw read是服務(wù)器返回給我們的字節(jié)內(nèi)容。

https報文格式:消息類型(第1字節(jié)),版本號(第2—3字節(jié)),消息體長度(第4—5字節(jié)),消息體(消息體長度個字節(jié))

(1)client_hello

客戶端發(fā)起請求,以明文傳輸請求信息,包含版本信息,加密套件候選列表,壓縮算法候選列表,隨機數(shù),擴展字段等信息,相關(guān)信息如下:

  • 支持的最高TSL協(xié)議版本version,從低到高依次 SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2,當前基本不再使用低于 TLSv1 的版本;
  • 客戶端支持的加密套件 cipher suites 列表, 每個加密套件對應(yīng)前面 TLS 原理中的四個功能的組合:認證算法 Au (身份驗證)、密鑰交換算法 KeyExchange(密鑰協(xié)商)、對稱加密算法 Enc (信息加密)和信息摘要 Mac(完整性校驗);
  • 支持的壓縮算法 compression methods 列表,用于后續(xù)的信息壓縮傳輸;
  • 隨機數(shù) random_C,用于后續(xù)的密鑰的生成;
  • 擴展字段 extensions,支持協(xié)議與算法的相關(guān)參數(shù)以及其它輔助信息等,常見的 SNI 就屬于擴展字段,后續(xù)單獨討論該字段作用。

(2).server_hello+server_certificate+sever_hello_done

  • server_hello, 服務(wù)端返回協(xié)商的信息結(jié)果,包括選擇使用的協(xié)議版本 version,選擇的加密套件 cipher suite,選擇的壓縮算法 compression method、隨機數(shù) random_S 等,其中隨機數(shù)用于后續(xù)的密鑰協(xié)商;
  • server_certificates, 服務(wù)器端配置對應(yīng)的證書鏈,用于身份驗證與密鑰交換;
  • server_hello_done,通知客戶端 server_hello 信息發(fā)送結(jié)束;

(3).證書校驗

  • [證書鏈]的可信性 trusted certificate path,方法如前文所述;
  • 證書是否吊銷 revocation,有兩類方式離線 CRL 與在線 OCSP,不同的客戶端行為會不同;
  • 有效期 expiry date,證書是否在有效時間范圍;
  • 域名 domain,核查證書域名是否與當前的訪問域名匹配,匹配規(guī)則后續(xù)分析;

(4).client_key_exchange+change_cipher_spec+encrypted_handshake_message

  • client_key_exchange,合法性驗證通過之后,客戶端計算產(chǎn)生隨機數(shù)字 Pre-master,并用證書公鑰加密,發(fā)送給服務(wù)器;
  • 此時客戶端已經(jīng)獲取全部的計算協(xié)商密鑰需要的信息:兩個明文隨機數(shù) random_C 和 random_S 與自己計算產(chǎn)生的 Pre-master,計算得到協(xié)商密鑰;
    enc_key=Fuc(random_C, random_S, Pre-Master)
  • change_cipher_spec,客戶端通知服務(wù)器后續(xù)的通信都采用協(xié)商的通信密鑰和加密算法進行加密通信;
  • encrypted_handshake_message,結(jié)合之前所有通信參數(shù)的 hash 值與其它相關(guān)信息生成一段數(shù)據(jù),采用協(xié)商密鑰 session secret 與算法進行加密,然后發(fā)送給服務(wù)器用于數(shù)據(jù)與握手驗證;(finished,校驗摘要信息?)

(5).change_cipher_spec+encrypted_handshake_message

  • 服務(wù)器用私鑰解密加密的 Pre-master 數(shù)據(jù),基于之前交換的兩個明文隨機數(shù) random_C 和 random_S,計算得到協(xié)商密鑰:enc_key=Fuc(random_C, random_S, Pre-Master);
  • 計算之前所有接收信息的 hash 值,然后解密客戶端發(fā)送的 encrypted_handshake_message,驗證數(shù)據(jù)和密鑰正確性;
  • change_cipher_spec, 驗證通過之后,服務(wù)器同樣發(fā)送 change_cipher_spec 以告知客戶端后續(xù)的通信都采用協(xié)商的密鑰與算法進行加密通信;
  • encrypted_handshake_message, 服務(wù)器也結(jié)合所有當前的通信參數(shù)信息生成一段數(shù)據(jù)并采用協(xié)商密鑰 session secret 與算法加密并發(fā)送到客戶端;(finished,校驗摘要信息?)

(6).握手結(jié)束

客戶端計算所有接收信息的 hash 值,并采用協(xié)商密鑰解密 encrypted_handshake_message,驗證服務(wù)器發(fā)送的數(shù)據(jù)和密鑰,驗證通過則握手完成;

(7).加密通信

開始使用協(xié)商密鑰與算法進行加密通信。
手摸手帶你認識https涉及的知識并實現(xiàn)通信

這是之前研究的流程,也放在這里好了。

1,瀏覽器將自己支持的一套加密規(guī)則發(fā)送給服務(wù)器端,如RSA加密算法,DES對稱加密算法,SHA1摘要算法。

2,服務(wù)器從中選出一組加密算法與HASH算法,并將證書發(fā)給瀏覽器。證書內(nèi)容包括了網(wǎng)站地址,加密公鑰等等。在握手的整個過程中,都用到了證書中的公鑰和瀏覽器發(fā)送給服務(wù)器的隨機密碼以及加密算法。(證書的內(nèi)容解析打印出來是一長串字節(jié),數(shù)字與字母的組合??蛻舳税l(fā)送過來的隨機數(shù)解析打印出來也是一長串字節(jié),數(shù)字與字母的組合)

3,客戶端拿到證書以后。

  • 驗證證書的合法性(頒發(fā)證書的機構(gòu)是否合法,證書中包含的網(wǎng)站地址是否與正在訪問的地址一致等),如果證書受信任,則瀏覽器欄里面會顯示一個小鎖頭,否則會給出證書不受信的提示。
  • 如果證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數(shù)的密碼,并用證書中提供的公鑰加密。
  • 使用約定好的HASH算法計算握手消息(如SHA1),并使用生成的隨機數(shù)對消息進行加密,最后將之前生成的被公鑰加密的隨機數(shù)密碼,HASH摘要值一起發(fā)送給服務(wù)器。

4,服務(wù)器收到客戶端發(fā)來的數(shù)據(jù)以后。

  • 使用自己的私鑰將信息解密并取出瀏覽器發(fā)送給服務(wù)器的隨機密碼,使用密碼解密瀏覽器發(fā)來的握手消息,并驗證HASH是否與瀏覽器發(fā)來的一致。
  • 使用隨機密碼加密一段握手消息,發(fā)送給瀏覽器。

    5,瀏覽器解密并計算握手消息的HASH,如果與服務(wù)端發(fā)來的HASH一致,此時握手過程結(jié)束,之后所有的通信數(shù)據(jù)將由之前瀏覽器生成的隨機密碼并利用對稱加密算法進行加密。

服務(wù)端啟用

以Tomcat為例,需要三步:創(chuàng)建keystore文件(保存了私鑰和公鑰);配置Tomcat SSL連接器;創(chuàng)建客戶端需要使用的電子證書。
獲去證書需要走以下幾步:

服務(wù)端人員需要使用keystore生成一個Certificate Signing Requst(csr文件)。

服務(wù)端人員把CSR文件發(fā)送給一個合法的CA機構(gòu),然后由CA機構(gòu)生成一個證書。

服務(wù)端人員把證書下下來,然后部署到服務(wù)器中。

SSL基于信任鏈來驗證站點證書的合法性,所以,你還要有一個CA的根證書,這個證書也需要從CA下載。把從CA下載的根證書和你通過CSR文件獲取的證書一起導入你的keystore。
客戶端訪問

客戶端往服務(wù)端發(fā)送加密數(shù)據(jù),首先得需要獲得公鑰,這個公鑰在保存在CA提供的證書中,所以客戶端首先得下載一個證書文件(一般是用戶代理自動下載)。

客戶端使用證書時,SSL會發(fā)送一個請求到證書中所指定的CA再次確認你的證書確實是從CA獲取的,而不是自己創(chuàng)建的??蛻舳诉€可以驗證服務(wù)端是否確實是自己調(diào)用的服務(wù)端。這兩步構(gòu)成了Peer Authentication。

服務(wù)端任務(wù)

1,獲取客戶端發(fā)送的支持的加密算法,包括hash算法。

2,發(fā)送證書給客戶端,(就是用流寫字節(jié))

3,獲取客戶端通過公鑰加密后的隨機數(shù),(就是流讀字節(jié))

4,私鑰解密公鑰加密后的隨機數(shù),得到解密后的隨機密碼。

5,獲取客戶端加密消息,(還是流讀取字節(jié))

6,用私鑰對消息解密(帶隨機數(shù))

7,解密出來數(shù)據(jù)后,采用約定的hash算法計算其hash值。

8,獲取客戶端發(fā)送過來的hash值,比較計算出來的hash值,是否一致。以判斷信息是否完整,是否被篡改。

9,如果第一次校驗客戶端發(fā)送過來的消息和摘要一致,服務(wù)器就開始向客戶端發(fā)送消息和摘要。

10,根據(jù)指定的算法和之前客戶端發(fā)送過來的隨機密碼(已解密的),生成密鑰。

11,用生成的密鑰加密發(fā)送給客戶端的數(shù)據(jù),發(fā)送給客戶端;用hash算法計算要發(fā)送給客戶端的數(shù)據(jù)的hash值,發(fā)送給客戶端,

客戶端任務(wù)

1,客戶端發(fā)送自己支持的hash算法

2,客戶端驗證服務(wù)器端證書是否合法

3,從證書里面獲取公鑰

4,生成隨機密碼,公鑰加密隨機密碼,發(fā)送給服務(wù)器。

5,使用公鑰和隨機密碼加密發(fā)送到服務(wù)器的數(shù)據(jù),發(fā)送給服務(wù)器。

5,使用hash算法計算發(fā)送到服務(wù)器的數(shù)據(jù)的hash值,發(fā)送給服務(wù)器。

6,接收服務(wù)器的數(shù)據(jù)。

7,公鑰,隨機密碼解密數(shù)據(jù)。

8,接收服務(wù)器的摘要信息。根據(jù)約定的hash算法,計算接收的數(shù)據(jù)的hash值,對比是否一致。

證書

沒有經(jīng)過認證的證書是不被瀏覽器信任的,所以當訪問的時候回提示不安全的網(wǎng)站,需要點擊信任之后才能繼續(xù)訪問。
手摸手帶你認識https涉及的知識并實現(xiàn)通信
而經(jīng)過認證的證書會提示安全,如下手摸手帶你認識https涉及的知識并實現(xiàn)通信

證書格式

證書格式(是一種標準):

x509 這種證書只有公鑰,不包含私鑰。

pcks#7 這種主要是用于簽名或者加密。

pcks#12 這種含有私鑰,同時也含有公鑰,但是有口令保護。

編碼方式:

.pem 后綴的證書都是base64編碼

.der 后綴的證書都是二進制格式

證書:

.csr 后綴的文件是用于向ca申請簽名的請求文件

.crt .cer 后綴的文件都是證書文件(編碼方式不一定,有可能是.pem,也有可能是.der)

私鑰:

.key 后綴的文件是私鑰文件

包含證書和私鑰:

.keystore .jks .truststore 后綴的文件,是java搞的,java可以用這個格式。這個文件中包含證書和私鑰,但是獲取私鑰需要密碼才可以,這是一個證書庫,里面可以保存多個證書和密鑰,通過別名可以獲取到。

.pfx 主要用于windows平臺,瀏覽器可以使用,也是包含證書和私鑰,獲取私鑰需要密碼才可以。

JKS和PKCS12都是比較常用的兩種密鑰庫格式/標準。JKS文件(通常為.jks或.keystore,擴展名無關(guān))可以通過Java原生工具——KeyTool生成;而后者PKCS#12文件(通常為.p12或.pfx,意味個人信息交換文件),則是通過更為常用的OpenSSL工具產(chǎn)生。

pfx轉(zhuǎn)keystore
keytool -importkeystore -v  -srckeystore jiaohangtest.pfx -srcstoretype pkcs12 -srcstorepass 111111 -destkeystore jiaohangtest.keystore -deststoretype jks -deststorepass 111111  

-importkeystore導入密鑰庫,通過格式設(shè)定,我們可以將PKCS#12文件轉(zhuǎn)換為JKS格式。
-v顯示詳情
-srckeystore源密鑰庫,這里是jiaohangtest.pfx
-srcstoretype源密鑰庫格式,這里為pkcs12
-srcstorepass源密鑰庫密碼,這里為111111
-destkeystore目標密鑰庫,這里為jiaohangtest.keystore
-deststoretype目標密鑰庫格式,這里為jks,默認值也如此
-deststorepass目標密鑰庫密碼,這里為111111
通過這個操作,我們能夠獲得所需的密鑰庫文件zlex.keystore。

手摸手帶你認識https涉及的知識并實現(xiàn)通信

keytool -list -keystore jiaohangtest.keystore -storepass 111111 -v  

-list列舉密鑰庫
-keystore密鑰庫,這里是jiaohangtest.keystore
-storepass密鑰庫密碼,這里是111111
-v顯示詳情
手摸手帶你認識https涉及的知識并實現(xiàn)通信

導出證書

keytool -exportcert -alias {3ff077c0-db58-4a2c-90d7-010189f6cefb} -keystore jiaohangtest.keystore -file jiaohangtest.crt -storepass 111111  

-exportcert導出證書
-alias別名,這里是 {3ff077c0-db58-4a2c-90d7-010189f6cefb}
-keystore密鑰庫,這里是jiaohangtest.keystore
-file證書文件,這里是jiaohangtest.crt
-storepass密鑰庫密碼,這里是111111
手摸手帶你認識https涉及的知識并實現(xiàn)通信

讀取.pfx
package com.lgx.https;

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Enumeration;

public class ReadPFX {

    public static void main(String[] args) throws Exception {
        String strPfx = "F:\\temp\\jiaohangtest.pfx";
        String strPassword = "111111";

        KeyStore ks = KeyStore.getInstance("PKCS12");
        FileInputStream fis = new FileInputStream(strPfx);
        char[] nPassword = null;
        if ((strPassword == null) || strPassword.trim().equals("")) {
            nPassword = null;
        } else {
            nPassword = strPassword.toCharArray();
        }

        ks.load(fis, nPassword);
        fis.close();

        System.out.println("keystore type !!!! " + ks.getType());

        Enumeration enumas = ks.aliases();
        String keyAlias = null;
        if (enumas.hasMoreElements()) {
            keyAlias = (String) enumas.nextElement();
            System.out.println("alias !!!! [" + keyAlias + "]");
        }

        System.out.println("is key entry !!!! " + ks.isKeyEntry(keyAlias));

        Certificate cert = ks.getCertificate(keyAlias);
        PublicKey pubkey = cert.getPublicKey();
        System.out.println("cert class !!!! " + cert.getClass().getName());
        System.out.println("cert !!!! " + cert);
        System.out.println("public key !!!! " + pubkey);

        PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword);
        System.out.println("private key !!!! " + prikey);
    }
}

輸出如下

keystore type !!!! PKCS12
alias !!!! [{3ff077c0-db58-4a2c-90d7-010189f6cefb}]
is key entry !!!! true
cert class !!!! sun.security.x509.X509CertImpl
cert !!!! [
[
  Version: V3
  Subject: CN=051@jiaohangtest2@Z12345678901@1, OU=Organizational-1, OU=Local RA, O=CFCA RSA OCA31, C=CN
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 27219026236566349676278543447695375821537131764213764580895621448617632840463012733407589298240130544810940254833865001134586287635536508023253272393470122815872601665690698359526947386480037704033149894017185905489409977845275027358025763252225165118227829757171401188153059476140198069888463051402042743179549693774973935701815888962610002471386320725949095454554681593598103249492940889302817758252011976833716892709723630945029012490500023246857692037901903024896848360887897268368940501163760211857657590438271663560769836982531695807471679797574531184632714885375902799523799220838320847415989537425934837932621
  public exponent: 65537
  Validity: [From: Thu Aug 23 14:49:12 CST 2018,
               To: Mon Aug 23 14:49:12 CST 2021]
  Issuer: CN=CFCA ACS TEST OCA31, O=China Financial Certification Authority, C=CN
  SerialNumber: [    40039449 98]

Certificate Extensions: 7
[1]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false
AuthorityInfoAccess [
  [
   accessMethod: ocsp
   accessLocation: URIName: http://ocsptest.cfca.com.cn:80/ocsp
]
]

[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 9A 3D B4 AE 65 58 FB CE   5A 05 78 26 A0 6D 2B 04  .=..eX..Z.x&.m+.
0010: 86 BA C6 EC                                        ....
]
]

[3]: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
  CA:false
  PathLen: undefined
]

[4]: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
  [DistributionPoint:
     [URIName: http://210.74.42.3/OCA31/RSA/crl39.crl]
]]

[5]: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
  clientAuth
  emailProtection
]

[6]: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
  Non_repudiation
]

[7]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: DE 86 85 A3 55 12 26 89   43 D5 14 77 A7 B9 06 8F  ....U.&.C..w....
0010: EA D4 CE B9                                        ....
]
]

]
  Algorithm: [SHA256withRSA]
  Signature:
0000: 8A 51 60 08 9A 33 EB 05   1F 74 1A 72 8D 4D 66 83  .Q`..3...t.r.Mf.
0010: A4 34 97 C6 FD 2A 14 AD   86 B6 A1 B5 80 C8 16 E8  .4...*..........
0020: 3B 56 18 36 D0 26 2F C6   FE AF F2 06 34 DC AC 64  ;V.6.&/.....4..d
0030: 29 5C 75 29 4F F7 76 49   54 E3 36 31 43 58 4D 1A  )\u)O.vIT.61CXM.
0040: 73 7D 6B 8E 74 C3 DC 57   AD A7 64 2E 70 D0 5C 7A  s.k.t..W..d.p.\z
0050: 37 61 81 97 83 26 55 D2   40 44 75 60 D4 76 1A 18  7a...&U.@Du`.v..
0060: EA 14 DF D7 1D 98 CB 6F   08 C6 C7 3A 0E 26 F9 ED  .......o...:.&..
0070: 7B 9D A1 C6 FA 90 15 8C   8F C8 06 52 F6 1A 54 F6  ...........R..T.
0080: 3C 60 BC 3A 2E DE 7E 2E   A8 16 0E AD 08 66 9C FF  <`.:.........f..
0090: 0F C5 F7 EF ED 4A 40 67   DC 0F 1E 01 EA 02 7B 06  .....J@g........
00A0: E8 C5 1C 15 E9 07 47 C8   DE 55 3B 17 4B 58 87 EF  ......G..U;.KX..
00B0: 41 BD 70 26 F5 4E 46 4C   2C 26 CC 0D DA F5 E7 4E  A.p&.NFL,&.....N
00C0: 72 85 7B 68 AA 6D FC DA   B6 08 5E ED 26 8B 44 7A  r..h.m....^.&.Dz
00D0: 5A BB 2F 69 7B 64 60 67   06 16 75 DB D1 0D 3D 54  Z./i.d`g..u...=T
00E0: 0E 05 82 38 CD EC 09 46   75 BD A5 4A 03 14 27 2A  ...8...Fu..J..'*
00F0: D2 78 F7 DB 10 4A 0B 71   74 B7 6F 67 6C 9E 1A 5B  .x...J.qt.ogl..[

]
public key !!!! Sun RSA public key, 2048 bits
  modulus: 27219026236566349676278543447695375821537131764213764580895621448617632840463012733407589298240130544810940254833865001134586287635536508023253272393470122815872601665690698359526947386480037704033149894017185905489409977845275027358025763252225165118227829757171401188153059476140198069888463051402042743179549693774973935701815888962610002471386320725949095454554681593598103249492940889302817758252011976833716892709723630945029012490500023246857692037901903024896848360887897268368940501163760211857657590438271663560769836982531695807471679797574531184632714885375902799523799220838320847415989537425934837932621
  public exponent: 65537
private key !!!! sun.security.rsa.RSAPrivateCrtKeyImpl@ffa5f146

加密:公鑰放在客戶端,并使用公鑰對數(shù)據(jù)進行加密,服務(wù)端拿到數(shù)據(jù)后用私鑰進行解密;

加簽:私鑰放在客戶端,并使用私鑰對數(shù)據(jù)進行加簽,服務(wù)端拿到數(shù)據(jù)后用公鑰進行驗簽。

前者完全為了加密;后者主要是為了防惡意***,防止別人模擬我們的客戶端對我們的服務(wù)器進行***,導致服務(wù)器癱瘓。

手摸手帶你認識https涉及的知識并實現(xiàn)通信

不管是客戶端還是服務(wù)端,都要存以下兩樣keystore。

KeyStore:保存自己的公鑰和私鑰。
Trust KeyStore:保存對方的公鑰證書。

單向認證

是客戶端信任服務(wù)端,

服務(wù)器端的KeyStore存儲自己的公鑰和私鑰,客戶端的Trust KeyStore要導入服務(wù)器端的公鑰證書。

雙向認證

是客戶端既要信任服務(wù)端而且服務(wù)端也要信任客戶端。

服務(wù)器端的KeyStore存儲自己的公鑰和私鑰,客戶端的Trust KeyStore要導入服務(wù)器端的公鑰證書。

客戶端的KeyStore存儲自己的公鑰和私鑰,服務(wù)器端的Trust KeyStore要導入客戶端的公鑰證書。

加密/解密

對稱加密算法

就是加密和解密都是用同一個秘鑰,這種方式優(yōu)點就是速度快,缺點就是在管理和分配秘鑰的時候不安全。

DES

(Data Encryption Standard):數(shù)據(jù)加密標準,速度較快,適用于加密大量數(shù)據(jù)的場合。

3DES

(Triple DES):是基于DES,對一塊數(shù)據(jù)用三個不同的密鑰進行三次加密,強度更高。

AES

(Advanced Encryption Standard):高級加密標準,是下一代的加密算法標準,速度快,安全級別高;

非對稱加密算法

非對稱加密有一個秘鑰對,叫做公鑰和私鑰,私鑰自己持有,公鑰可以公開的發(fā)送給使用的人。使用公鑰進行加密的信息,只有和其配對的私鑰可以解開。使用私鑰鑰進行加密的信息,只有和其配對的公鑰可以解開。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。

RSA算法
由 RSA 公司發(fā)明,是一個支持變長密鑰的公共密鑰算法,需要加密的文件塊的長度也是可變的; 

RSA是第一個也是目前唯一一個既能用于密鑰交換又能用于數(shù)字簽名的算法。
DSA

(Digital Signature Algorithm):數(shù)字簽名算法,是一種標準的 DSS(數(shù)字簽名標準);

ECC

(Elliptic Curves Cryptography):橢圓曲線密碼編碼學。

綜合
一般都是對稱加密和非對稱加密結(jié)合使用,使用非對稱加密完成秘鑰的傳遞,然后使用對稱秘鑰進行數(shù)據(jù)加密和解密。
比如RSA非對稱加密,對加密的內(nèi)容有長度限制,長度過長就不行。

加簽/驗簽

哈希算法

抗篡改能力,通常用于文件校驗,數(shù)字簽名,鑒權(quán)協(xié)議。

加密過程不需要密鑰,并且經(jīng)過加密的數(shù)據(jù)無法被解密,只有輸入相同的明文數(shù)據(jù)經(jīng)過相同的消息摘要算法才能得到相同的密文。接收者通過對收到消息的新產(chǎn)生的摘要與原摘要比較,就可知道消息是否被改變了。

只要輸入的消息不同,對其進行摘要以后產(chǎn)生的摘要消息也必不相同;但相同的輸入必會產(chǎn)生相同的輸出。而且只能進行正向的信息摘要,而無法從摘要中恢復出任何的消息,甚至根本就找不到任何與原信息相關(guān)的信息。

MD4

(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年設(shè)計的,MD 是 Message Digest 的縮寫。其輸出為 128 位。MD4 已證明不夠安全。

MD5

(RFC 1321)是 Rivest 于1991年對 MD4 的改進版本。它對輸入仍以 512 位分組,其輸出是 128 位。MD5 比 MD4 復雜,并且計算速度要慢一點,更安全一些。MD5 已被證明不具備”強抗碰撞性”。

SHA

(Secure Hash Algorithm)是一個 Hash 函數(shù)族,由 NIST(National Institute of Standards and Technology)于 1993 年發(fā)布第一個算法。目前知名的 SHA-1 在 1995 年面世,它的輸出為長度 160 位的 hash 值,因此抗窮舉性更好。SHA-1 設(shè)計時基于和 MD4 相同原理,并且模仿了該算法。SHA-1 已被證明不具”強抗碰撞性”。
? 為了提高安全性,NIST 還設(shè)計出了 SHA-224、SHA-256、SHA-384,和 SHA-512 算法(統(tǒng)稱為 SHA-2),跟 SHA-1 算法原理類似。SHA-3 相關(guān)算法也已被提出。

Java實現(xiàn)https

證書信任

Java安全套接擴展 (Java Secure Socket Extension, JSSE)是實現(xiàn)Internet安全通信的一系列包的集合。它是一個SSL和TLS的純Java實現(xiàn)。

TrustManager接口

JSSE中,有一個信任管理器類負責決定是否信任遠端的證書;一般的,僅會有一個支持基于X.509(數(shù)字證書標準)公鑰認證的TrustManager。

  • 如果系統(tǒng)屬性javax.net.sll.trustStore指定了TrustStore文件(客戶端的TrustStore文件中保存著被客戶端所信任的服務(wù)器的證書信息),那么信任管理器就去jre安裝路徑下的lib/security/目錄中尋找并使用這個文件來檢查證書。

  • 如果該系統(tǒng)屬性沒有指定TrustStore文件,它就會去jre安裝路徑下尋找默認的TrustStore文件,這個文件的相對路徑為:lib/security/jssecacerts。

  • 如果 jssecacerts不存在,但是cacerts存在(它隨J2SDK一起發(fā)行,含有數(shù)量有限的可信任的基本證書),那么這個默認的TrustStore文件就是cacerts。

直接使用類HttpsURLConnection訪問Web頁面,如果站點的安全證書不被JSSE所信任,訪問就報錯,如果站點的證書被JSEE內(nèi)置信任就訪問OK。

對于不被JSSE所默認信任的,一種解決方法是把站點的證書放到證書庫文件jssecacerts中, 或者把證書存放到任一TrustStore文件中,然后設(shè)置系統(tǒng)屬性javax.net.sll.trustStore指向該文件。另一種解決方法則是自己實現(xiàn)信任管理器類,讓它信任我們指定的證書。

1,將證書導入到TrustStore文件中

Java提供了命令行工具keytool用于創(chuàng)建證書或者把證書從其它文件中導入到Java自己的TrustStore文件中。

  取得源證書文件,把這個文件復制到j(luò)re安裝路徑下的lib/security/目錄中。這樣,只需在程序中設(shè)置系統(tǒng)屬性javax.net.sll.trustStore指向文件dest_cer_store,就能使JSSE信任該證書,從而使程序可以訪問使用未經(jīng)驗證的證書的HTTPS站點。

  使用這種方法,編程非常簡單,但需要手工導出服務(wù)器的證書。當服務(wù)器證書經(jīng)常變化時,就需要經(jīng)常進行手工導出證書的操作。

2,X509證書信任管理器類的實現(xiàn)及應(yīng)用

進行SSL的驗證或者過濾之后才能夠訪問。

package com.lgx.http;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;

/**
    在JSSE中,證書信任管理器類就是實現(xiàn)了接口X509TrustManager的類。
    我們可以自己實現(xiàn)該接口,讓它信任我們指定的證書。
    當方法為空是默認為所有的鏈接都為安全,也就是所有的鏈接都能夠訪問到。
    接口X509TrustManager有下述三個公有的方法需要我們實現(xiàn):
**/

public class MyX509TrustManager implements X509TrustManager {

    /*
        該方法檢查客戶端的證書,若不信任該證書則拋出異常。
        由于我們不需要對客戶端進行認證,因此我們只需要執(zhí)行默認的信任管理器的這個方法。
        JSSE中,默認的信任管理器類為TrustManager。
    */
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {

    }

    /*
        該方法檢查服務(wù)器的證書,若不信任該證書同樣拋出異常。
        通過自己實現(xiàn)該方法,可以使之信任我們指定的任何證書。
        可以不做任何處理,即一個空的函數(shù)體,由于不會拋出異常,它就會信任任何證書。
    */
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {

    }

    /*
        返回受信任的X509證書數(shù)組。
    */
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }

}
package com.lgx.http;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
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 Https {

    /*
     * 處理https GET/POST請求 請求地址、請求方法、參數(shù)
     */
    public static String httpsRequest(String requestUrl, String requestMethod,
            String outputStr) {
        StringBuffer buffer = null;
        try {
            // 1,創(chuàng)建SSLContext,并使用我們指定的信任管理器初始化
            SSLContext sslContext = SSLContext.getInstance("SSL");
            TrustManager[] tm = { new MyX509TrustManager() };
            sslContext.init(null, tm, new java.security.SecureRandom());

            // 2,獲取SSLSocketFactory對象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            // 創(chuàng)建HttpsURLConnection對象,并設(shè)置其SSLSocketFactory對象
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

            //屬性設(shè)置
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod(requestMethod);
            // 設(shè)置當前實例使用的SSLSoctetFactory,12只和這一步有關(guān)。
            conn.setSSLSocketFactory(ssf);

            //連接
            conn.connect();

            // 往服務(wù)器端寫內(nèi)容
            if (null != outputStr) {
                OutputStream os = conn.getOutputStream();
                os.write(outputStr.getBytes("utf-8"));
                os.close();
            }

            // 讀取服務(wù)器端返回的內(nèi)容
            InputStream is = conn.getInputStream();
            InputStreamReader isr = new InputStreamReader(is, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            buffer = new StringBuffer();
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }

    public static void main(String[] args) {
        String s = httpsRequest("https://www.baidu.com/", "POST", null);
        //不是https,用http,程序就會報錯。
        //String s = httpsRequest("http://www.baidu.com/", "POST", null);
        System.out.println(s);
    }

}
KeyManager接口

決定將哪一個認證證書發(fā)送給對端服務(wù)器,單向認證,就會傳一個null,

完整代碼實現(xiàn)

讀pfx取東西

package com.lgx.https;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

public class ReadKeystore {

    public String keyStorePath = "././resource/jiaohangtest.keystore";
    public String certificatePath = "././resource/jiaohangtest.crt";
    public String alias = "{3ff077c0-db58-4a2c-90d7-010189f6cefb}";
    public String keyStorePassword = "111111";
    public String aliasPassword = "111111";

    public String trustCertificatePath = "././resource/wanglian-rsa.cer";

    // 獲得KeyStore
    public KeyStore keyStoreFromKeystore() {
        FileInputStream is;
        KeyStore keyStore = null;
        try {
            is = new FileInputStream(keyStorePath);
            keyStore = KeyStore.getInstance("JKS");
            keyStore.load(is, keyStorePassword.toCharArray());
            is.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return keyStore;
    }

    // 取證書
    public Certificate certificateFormKeystore() {
        KeyStore keyStore = keyStoreFromKeystore();
        Certificate certificate = null;
        try {
            certificate = keyStore.getCertificate(alias);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }

        return certificate;
    }

    // 獲得私鑰
    public PrivateKey privateKeyFormKeystore() {
        KeyStore keyStore = keyStoreFromKeystore();

        PrivateKey prikey = null;
        try {
            prikey = (PrivateKey) keyStore.getKey(alias, aliasPassword
                    .toCharArray());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return prikey;
    }

    // 讀取公鑰
    public PublicKey publicKeyFormKeystore() {
        Certificate certificate = certificateFormKeystore();

        PublicKey pubkey = null;
        try {
            pubkey = certificate.getPublicKey();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return pubkey;

    }

    // 由證書路徑獲得Certificate
    public Certificate getCertificate(String certificatePath) {
        CertificateFactory certificateFactory;
        Certificate certificate = null;
        try {
            certificateFactory = CertificateFactory.getInstance("X.509");
            FileInputStream in = new FileInputStream(certificatePath);

            certificate = certificateFactory.generateCertificate(in);
            in.close();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return certificate;
    }

    // 由證書路徑得公鑰
    public PublicKey getPublicKey() {
        Certificate certificate = getCertificate(certificatePath);
        PublicKey pubkey = null;
        try {
            pubkey = certificate.getPublicKey();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return pubkey;
    }

}

讀keystore取東西

package com.lgx.https;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Enumeration;

public class ReadPFX {

    String pfxPath = "././resource/jiaohangtest.pfx";
    String pfxPassword = "111111";

    // 讀取KeyStore
    public KeyStore keyStoreFromPFX() {
        KeyStore keyStore = null;
        try {
            keyStore = KeyStore.getInstance("PKCS12");
            FileInputStream fis = new FileInputStream(pfxPath);

            char[] nPassword = null;
            nPassword = pfxPassword.toCharArray();

            // 加載keystore
            keyStore.load(fis, nPassword);
            fis.close();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return keyStore;
    }

    // 讀取別名
    @SuppressWarnings("unchecked")
    public String aliasFromPFX() {
        KeyStore keyStore = keyStoreFromPFX();
        Enumeration enumas;
        String keyAlias = null;
        try {
            enumas = keyStore.aliases();
            if (enumas.hasMoreElements()) {
                keyAlias = (String) enumas.nextElement();
                System.out.println("alias !!!! [" + keyAlias + "]");
            }
            System.out.println("is key entry !!!! "
                    + keyStore.isKeyEntry(keyAlias));
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return keyAlias;
    }

    // 讀取證書
    public Certificate certificateFromPFX() {
        KeyStore keyStore = keyStoreFromPFX();
        String keyAlias = aliasFromPFX();
        Certificate cert = null;
        try {
            cert = keyStore.getCertificate(keyAlias);
            System.out.println("cert class !!!! " + cert.getClass().getName());
            System.out.println("cert !!!! " + cert);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return cert;

    }

    // 讀取公鑰
    public PublicKey publicKeyFromPFX() {
        Certificate cert = certificateFromPFX();
        PublicKey pubkey = cert.getPublicKey();
        System.out.println("public key !!!! " + pubkey);
        return pubkey;

    }

    // 讀取私鑰
    public PrivateKey privateKeyFromPFX() {
        KeyStore keyStore = keyStoreFromPFX();
        String keyAlias = aliasFromPFX();
        char[] nPassword = null;
        nPassword = pfxPassword.toCharArray();

        PrivateKey prikey = null;
        try {
            prikey = (PrivateKey) keyStore.getKey(keyAlias, nPassword);

        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return prikey;
    }
}

加簽,驗簽

package com.lgx.https;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.X509Certificate;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;

public class SignAndCheck {

    // 本地簽名,自己證書的私鑰
    public String SignatureData(String data) {
        byte[] signByte = null;

        ReadKeystore readKeystore = new ReadKeystore();
        // 獲得證書
        X509Certificate x509Certificate = (X509Certificate) readKeystore
                .certificateFormKeystore();
        // 取得私鑰
        PrivateKey privateKey = readKeystore.privateKeyFormKeystore();
        // 構(gòu)建簽名
        Signature signature;
        try {
            signature = Signature.getInstance(x509Certificate.getSigAlgName());
            signature.initSign(privateKey);
            signature.update(data.getBytes());
            signByte = signature.sign();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        }
        return Base64.encode(signByte);
    }

    // 服務(wù)器驗簽,自己證書的公鑰
    public boolean CheckSignature(String data, String sign) {
        boolean flag = true;
        ReadKeystore readKeystore = new ReadKeystore();
        // 獲得證書
        X509Certificate x509Certificate = (X509Certificate) readKeystore
                .certificateFormKeystore();
        // 獲得公鑰
        PublicKey publicKey = x509Certificate.getPublicKey();
        // 構(gòu)建簽名
        Signature signature;
        try {
            signature = Signature.getInstance(x509Certificate.getSigAlgName());
            signature.initVerify(publicKey);
            signature.update(data.getBytes());
            flag = signature.verify(Base64.decode(sign.getBytes()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (Base64DecodingException e) {
            e.printStackTrace();
        }

        return flag;
    }
}

加密,解密

package com.lgx.https;

import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;

import com.sun.org.apache.xml.internal.security.utils.Base64;

public class EncryAndDecry {

    // 本地加密,服務(wù)器的公鑰
    public String encryptDate(String data) throws Exception {
        byte[] encryptByte = null;
        ReadKeystore readKeystore = new ReadKeystore();
        // 取得公鑰
        PublicKey publicKey = readKeystore.publicKeyFormKeystore();
        // 對數(shù)據(jù)加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        encryptByte = cipher.doFinal(data.getBytes());
        return Base64.encode(encryptByte);

    }

    // 服務(wù)器解密,服務(wù)器的私鑰
    public String decryptDate(String data) throws Exception {
        byte[] decryptByte = null;

        // 取得私鑰
        ReadKeystore readKeystore = new ReadKeystore();
        PrivateKey privateKey = readKeystore.privateKeyFormKeystore();

        // 對數(shù)據(jù)解密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        decryptByte = cipher.doFinal(data.getBytes());
        return Base64.encode(decryptByte);

    }

}

數(shù)據(jù)加密解密

package com.lgx.https;

import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;

import com.sun.org.apache.xml.internal.security.utils.Base64;

public class EncryAndDecry {

    // 本地加密,服務(wù)器的公鑰
    public String encryptDate(String data) throws Exception {
        byte[] encryptByte = null;
        ReadKeystore readKeystore = new ReadKeystore();
        // 取得公鑰
        PublicKey publicKey = readKeystore.publicKeyFormKeystore();
        // 對數(shù)據(jù)加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        encryptByte = cipher.doFinal(data.getBytes());
        return Base64.encode(encryptByte);

    }

    // 服務(wù)器解密,服務(wù)器的私鑰
    public String decryptDate(String data) throws Exception {
        byte[] decryptByte = null;

        // 取得私鑰
        ReadKeystore readKeystore = new ReadKeystore();
        PrivateKey privateKey = readKeystore.privateKeyFormKeystore();

        // 對數(shù)據(jù)解密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        decryptByte = cipher.doFinal(data.getBytes());
        return Base64.encode(decryptByte);

    }

}

校驗服務(wù)器證書

package com.lgx.https;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class MyX509TrustManager implements X509TrustManager {

    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {

    }

    // 默認信任所有的HTTPS站點證書
    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {

    }

    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

}

socket連接管道

package com.lgx.https;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;

public class SSLUtil {
    public String KEY_STORE_PASS = "111111";

    private SSLContext sslContext;

    public String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            // 連接
            URL realUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) realUrl
                    .openConnection();

            // 套接socket
            if (connection instanceof HttpsURLConnection) {
                ((HttpsURLConnection) connection).setSSLSocketFactory(getSSLContext().getSocketFactory());
            }

            // 設(shè)置通用的請求屬性
            // 發(fā)送POST請求必須設(shè)置如下兩行
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 設(shè)置接收數(shù)據(jù)的格式
            connection.setRequestProperty("Accept", "*/*");
            connection.setRequestProperty("OriI***Id", "C1030131001288");
            connection.setRequestProperty("MsgTP", "uops.010.000.01");
            // 設(shè)置維持長連接
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Accept-Encoding", "gzip");
            // 設(shè)置文件字符集:
            connection.setRequestProperty("Charset", "UTF-8");
            // 設(shè)置發(fā)送數(shù)據(jù)的格式
            connection.setRequestProperty("Content-Type", "application/json");
            // 設(shè)置不用緩存,注意設(shè)置請求方法為post不能用緩存
            connection.setUseCaches(false);
            // 設(shè)置傳遞方式
            connection.setRequestMethod("POST");

            // 開始連接請求
            connection.connect();

            // 獲取URLConnection對象對應(yīng)的輸出流
            out = new PrintWriter(connection.getOutputStream());
            // 發(fā)送請求參數(shù)
            out.print(param);
            // flush輸出流的緩沖
            out.flush();

            // 讀取URL的響應(yīng),返回的流。如果有錯誤,返回錯誤的信息
            if (connection.getResponseCode() == 200) {
                in = new BufferedReader(new InputStreamReader(connection
                        .getInputStream(), "UTF-8"));
            } else {
                in = new BufferedReader(new InputStreamReader(connection
                        .getErrorStream(), "UTF-8"));
            }

            // 轉(zhuǎn)字符串
            String content = "";
            while ((content = in.readLine()) != null) {
                result += content;
            }

        } catch (Exception e) {
            System.out.println("發(fā)送 POST 請求出現(xiàn)異常!" + e);
            e.printStackTrace();
        }

        // 使用finally塊來關(guān)閉輸出流、輸入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        System.out.println(("getDataFromServer:" + result));
        return result;
    }

    public SSLContext getSSLContext() throws Exception {
        long time1 = System.currentTimeMillis();

        if (sslContext == null) {
            try {
                // 服務(wù)器要驗證客戶端證書
                KeyManagerFactory keyManagerFactory = KeyManagerFactory
                        .getInstance("SunX509");
                ReadKeystore readKeystore = new ReadKeystore();
                KeyStore keyStore = readKeystore.keyStoreFromKeystore();
                keyManagerFactory.init(keyStore, KEY_STORE_PASS.toCharArray());
                KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

                // 客戶端要驗證服務(wù)端證書
                TrustManager[] trustManagers = { new MyX509TrustManager() };

                // 初始化SSLContext實例
                sslContext = SSLContext.getInstance("TLSv1.2");
                sslContext.init(keyManagers, trustManagers, new SecureRandom());

                //繞過ip直連https,證書校驗
                HttpsURLConnection
                        .setDefaultHostnameVerifier(new HostnameVerifier() {
                            public boolean verify(String hostname,
                                    SSLSession session) {
                                return true;
                            }
                        });
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                e.printStackTrace();
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
        }

        long time2 = System.currentTimeMillis();
        System.out.println("SSLContext 初始化時間:" + (time2 - time1));
        return sslContext;
    }
}

測試

package com.lgx.https;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class HttpsTest {

    public static String url = "https://221.122.73.116:443/uopsSvr";

    public static void main(String[] args) throws Exception {

        SignAndCheck signAndCheck = new SignAndCheck();
        EncryAndDecry encryAndDecry = new EncryAndDecry();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

        String head = "'msgTp':'uops.010.000.01','msgSndTm':'"
                + sdf.format(new Date())
                + "','msgId':'"
                + sdf.format(new Date())
                + "00000000000000000000000000000000000000000000000001',"
                + "'i***Id':'G4000311000018','reI***Id':'C1030131001288','drctn':'02','signSN':'4000068829'";

        String body = "'cntStep':'60','cntTm':'"
                + sdf.format(new Date())
                + "','tList':[{"
                + "'tType':'0201','instId':'z2004944000010','accType':'01','RPFlg':'1','tSumNo':'"
                + (new Random().nextInt(10000) + 10000)
                + "','tTime':'347.45','tTrxSR':'99.9567','tSy***':'99.8989'"
                + "},{'tType':'0202','instId':'z2004944000010','accType':'00','RPFlg':'0','tSumNo':'"
                + (new Random().nextInt(10000) + 10000)
                + "','tTime':'321.45','tTrxSR':'99.9664','tSy***':'99.2129'}]";

        String data = "msgTp=uops.010.000.01&msgSndTm="
                + sdf.format(new Date())
                + "&msgId="
                + sdf.format(new Date())
                + "00000000000000000000000000000000000000000000000001"
                + "&i***Id=G4000311000018&reI***Id=C1030131001288&drctn=02&signSN=4000068829";

        String encryptBody = encryAndDecry.encryptDate(body);

        String signature = signAndCheck.SignatureData(data);

        String param = "{'request':{'head':{" + head + "},'body':{"
                + encryptBody + "}},'signature':'" + signature + "'}";

        SSLUtil sslUtil = new SSLUtil();
        String result = sslUtil.sendPost(url, param);
        System.out.println(result);
    }
}
測試過程中問題

經(jīng)過代理服務(wù)器連接的https

package com.lgx.ssl;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;

/*
 * 經(jīng)過代理服務(wù)器后,由代理服務(wù)器走HTTPS。
 */
public class ProxyHttps {
    public static void main(String[] args) throws Throwable {

        // HTTPS詳細過程
        System.setProperty("javax.net.debug", "all");

        String xmlServerURL = "https://www.baidu.com/";

        URL urlXMLServer = new URL(xmlServerURL);
        // 我自己的代理服務(wù)器
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("172.31.219.169", 808));
        HttpURLConnection httpsURLConnection = (HttpURLConnection) urlXMLServer.openConnection(proxy);

        httpsURLConnection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
        httpsURLConnection.setDoInput(true);
        httpsURLConnection.setDoOutput(true);
        httpsURLConnection.setUseCaches(false);
        httpsURLConnection.setRequestMethod("POST");
        httpsURLConnection.connect();

        PrintWriter out = new PrintWriter(httpsURLConnection.getOutputStream());
        // 傳參數(shù)
        out.print("777");
        out.flush();
        out.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));

        String result = "";
        String content = "";
        while ((content = in.readLine()) != null) {
            result += content;
        }

        String line;
        String respXML = "";
        while ((line = in.readLine()) != null) {
            respXML += line;
        }
        in.close();

        System.out.println(("getDataFromServer:" + result));
    }

}

ip訪問https

由于請求的HOST被替換成了IP,導致底層在進行證書的HOST校驗時失敗,最終請求失敗。

public static void main(String[] args) throws Exception{
    SSLContext sslcontext = SSLContext.getInstance("SSL");
    sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
    URL url = new URL("https://xxxx");

    HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
        public boolean verify(String s, SSLSession sslsession) {
            System.out.println("WARNING: Hostname is not matched for cert.");
                return true;
            }
        };                                          HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
     HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());

}

經(jīng)過投產(chǎn),代碼穩(wěn)定運行兩年

拓展

網(wǎng)絡(luò)協(xié)議

手摸手帶你認識https涉及的知識并實現(xiàn)通信

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI