手摸手带你认识https涉及的知识并实现通信
@[toc]
看完整的代码,直接去完整代码实现
,看实现完后会遇到的坑,直接去测试过程中的问题
,包括经过代理服务器访问https,通过ip访问https等。
我们开发java web项目时,打好war包放到tomcat应用服务器的webapps目录下,tomcat的访问端口是8080,启动tomcat,在浏览器的地址栏输入http://localhost:8080。就会看到如下
那么,看看服务器到底返回了什么内容,在web项目中,运行代码
package com.lgx.http;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;public class t1 { /* 测试http请求服务器,看服务器返回了什么东西。 */ 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页面字节数远远小于1024 byte[] bytes = new byte[1024]; int bytesLength = input.read(bytes); System.out.println("服务器返回:\n" + new String(bytes, 0, bytesLength)); connection.disconnect(); } catch (Exception e) { e.printStackTrace(); } }}
得到结果如下
上面其实并不是完整的服务器返回给浏览器的内容,被我们输出的只是http报文体,但这并不重要!可以看出数据并未加密。
https访问流程更改上述代码,把URL的http改为https,会报错。需要配置一下tomcat服务器
配置tomcat配置支持https访问,如果使用nginx还需配nginx。
创建密钥库用Java自带的keytool生成一个秘钥库
keytool -genkey -alias "tomcat" -keyalg "RSA" -keysize 1024 -validity 365 -keystore "/Users/liguoxi/Public/tomcat.keystore"
秘密设置为123456
注:KeyStore一般用JDK中的keytool生成。Keytool使用RSA或DSA KeyPairGenerator生成一个秘钥对并连同新生成的证书一起存入KeyStore文件中。
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一致,服务器发过来的证书,要存在于信任秘钥库中 System.setProperty("javax.net.ssl.trustStore", "/Users/liguoxi/Public/tomcat.keystore"); // 信任秘钥库密码 System.setProperty("javax.net.ssl.trustStorePassword", "123456"); // https协议版本 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) { // 证书里面有个扩展域,记录了服务器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("服务器返回:\n" + new String(bytes, 0, bytesLength)); connection.disconnect(); } catch (Exception e) { e.printStackTrace(); } }}
输出一大堆
trustStore is: /Users/liguoxi/Public/tomcat.keystoretrustStore type is : jkstrustStore provider is : init truststoreadding 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 2019keyStore is : keyStore type is : jkskeyStore provider is : init keystoreinit keymanager of type SunX509trigger seeding of SecureRandomdone seeding SecureRandomAllow unsafe renegotiation: falseAllow legacy hello messages: trueIs initial handshake: trueIs secure renegotiation: falsemain, setSoTimeout(0) calledIgnoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_GCM_SHA256Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256%% No cached client session*** ClientHello, TLSv1RandomCookie: 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 = 1250000: 01 00 00 79 03 01 5B BA 1E 06 CE DD BE D7 CB 4B ...y..[........K0010: 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 = 1300000: 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 = 50000: 16 03 01 03 74 ....t[Raw read]: length = 8840000: 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..F00060: 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....LG0090: 58 31 0C 30 0A 06 03 55 04 08 13 03 4C 47 58 31 X1.0...U....LGX100A0: 0C 30 0A 06 03 55 04 07 13 03 4C 47 58 31 0C 30 .0...U....LGX1.000B0: 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...U00D0: 04 03 13 03 4C 47 58 30 1E 17 0D 31 38 31 30 30 ....LGX0...1810000E0: 37 31 33 32 37 35 38 5A 17 0D 31 39 31 30 30 37 7132758Z..19100700F0: 31 33 32 37 35 38 5A 30 54 31 0C 30 0A 06 03 55 132758Z0T1.0...U0100: 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....LG0130: 58 31 0C 30 0A 06 03 55 04 0B 13 03 4C 47 58 31 X1.0...U....LGX10140: 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,.601C0: 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 g02A0: 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+.1r02D0: 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<#A0330: 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, TLSv1RandomCookie: 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_SHACompression Method: 0Extension 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 = 850000: 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 chainchain [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=falseSubjectKeyIdentifier [KeyIdentifier [0000: E0 A4 47 46 87 0B 8D 4F A6 B2 29 57 D7 1D 59 78 ..GF...O..)W..Yx0010: 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...b0040: 0F 15 EF 5C 19 F2 D7 C7 5E DC F3 FD F6 A1 F3 30 ...\....^......00050: 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=falseSubjectKeyIdentifier [KeyIdentifier [0000: E0 A4 47 46 87 0B 8D 4F A6 B2 29 57 D7 1D 59 78 ..GF...O..)W..Yx0010: 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...b0040: 0F 15 EF 5C 19 F2 D7 C7 5E DC F3 FD F6 A1 F3 30 ...\....^......00050: 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 = 5920000: 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....L0080: 47 58 30 1E 17 0D 31 38 31 30 30 37 31 33 32 37 GX0...18100713270090: 35 38 5A 17 0D 31 39 31 30 30 37 31 33 32 37 35 58Z..1910071327500A0: 38 5A 30 54 31 0C 30 0A 06 03 55 04 06 13 03 4C 8Z0T1.0...U....L00B0: 47 58 31 0C 30 0A 06 03 55 04 08 13 03 4C 47 58 GX1.0...U....LGX00C0: 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.60120: 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]..o0190: 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...b0210: 0F 15 EF 5C 19 F2 D7 C7 5E DC F3 FD F6 A1 F3 30 ...\....^......00220: 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 ServerKeyExchangeServer 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 = 2030000: 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,10050: 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.G00A0: 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 = 40000: 0E 00 00 00 ....*** ECDHClientKeyExchangeECDH 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 = 700000: 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....=L0020: CA F1 94 DD CA 7D E6 CD F2 7C 52 C3 69 83 16 4E ..........R.i..N0030: 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>..Ymain, WRITE: TLSv1 Handshake, length = 70[Raw write]: length = 750000: 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..........R0030: 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>..YSESSION 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.rtCONNECTION 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.qo0010: 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\9A0010: 07 99 B9 46 ...FClient 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 = 60000: 14 03 01 00 01 01 ......*** Finishedverify_data: { 138, 44, 121, 7, 61, 112, 195, 10, 93, 222, 35, 164 }***[write] MD5 and SHA1 hashes: len = 160000: 14 00 00 0C 8A 2C 79 07 3D 70 C3 0A 5D DE 23 A4 .....,y.=p..].#.Padded plaintext before ENCRYPTION: len = 480000: 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 = 530000: 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 = 50000: 14 03 01 00 01 .....[Raw read]: length = 10000: 01 .main, READ: TLSv1 Change Cipher Spec, length = 1[Raw read]: length = 50000: 16 03 01 00 30 ....0[Raw read]: length = 480000: 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 = 48Padded plaintext after DECRYPTION: len = 480000: 14 00 00 0C C0 1E 82 40 64 A8 15 62 8D DC A0 62 .......@d..b...b0010: 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 ................*** Finishedverify_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 = 160000: 14 00 00 0C C0 1E 82 40 64 A8 15 62 8D DC A0 62 .......@d..b...bPadded plaintext before ENCRYPTION: len = 1760000: 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: Java0020: 2F 31 2E 38 2E 30 5F 31 36 31 0D 0A 48 6F 73 74 /1.8.0_161..Host0030: 3A 20 6C 6F 63 61 6C 68 6F 73 74 3A 38 34 34 33 : localhost:84430040: 0D 0A 41 63 63 65 70 74 3A 20 74 65 78 74 2F 68 ..Accept: text/h0050: 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, *; q0070: 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: keep0090: 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 = 1810000: 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....l0040: 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 = 50000: 17 03 01 01 40 ....@[Raw read]: length = 3200000: B0 AA 6A 6E F6 37 D3 C6 66 BB 17 A7 27 F3 3C 74 ..jn.7..f...'.<t0010: 6A DF 16 C5 9E F8 34 BB B6 8E FA FE 6E 52 F4 39 j.....4.....nR.90020: 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....i0050: 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..w0070: 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......m00B0: 22 04 95 F7 7A 68 FA 84 0B B8 CE F1 B5 3B 09 6F "...zh.......;.o00C0: A8 DF 7C C7 0B A7 D7 68 17 EF F3 57 5D 01 D5 54 .......h...W]..T00D0: D1 05 8E 69 AA 68 CB 75 9F A7 45 2E 7B 0B 9A 5A ...i.h.u..E....Z00E0: 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...[..$.l0130: 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 = 320Padded plaintext after DECRYPTION: len = 3200000: 48 54 54 50 2F 31 2E 31 20 32 30 30 20 0D 0A 53 HTTP/1.1 200 ..S0010: 65 74 2D 43 6F 6F 6B 69 65 3A 20 4A 53 45 53 53 et-Cookie: JSESS0020: 49 4F 4E 49 44 3D 35 38 35 38 35 45 35 44 44 42 IONID=58585E5DDB0030: 32 46 41 43 39 33 44 37 30 43 30 31 32 43 34 33 2FAC93D70C012C430040: 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; HttpOnly0060: 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;charse0080: 74 3D 55 54 46 2D 38 0D 0A 43 6F 6E 74 65 6E 74 t=UTF-8..Content0090: 2D 4C 65 6E 67 74 68 3A 20 39 30 0D 0A 44 61 74 -Length: 90..Dat00A0: 65 3A 20 53 75 6E 2C 20 30 37 20 4F 63 74 20 32 e: Sun, 07 Oct 200B0: 30 31 38 20 31 34 3A 35 33 3A 35 38 20 47 4D 54 018 14:53:58 GMT00C0: 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>. <title00E0: 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>. <bo0100: 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>..W0120: 3B 52 9A FF 6D BC FF 62 7F 2E E1 D3 09 6E 28 6E ;R..m..b.....n(n0130: 1D 5A 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D .Z..............服务器返回:<html> <head> <title>$Title$</title> </head> <body> $END$ </body></html>main, called close()main, called closeInternal(true)main, SEND TLSv1 ALERT: warning, description = close_notifyPadded plaintext before ENCRYPTION: len = 320000: 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 = 370000: 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.j0020: 3E 10 46 0C FD >.F..main, called closeSocket(true)Process finished with exit code 0
流程概述
什么意思?
[Raw write]和[Raw read],我们和tomcat服务器之间建立socket连接之后,Raw write是我们写给服务器的字节内容,Raw read是服务器返回给我们的字节内容。
https报文格式:消息类型(第1字节),版本号(第2—3字节),消息体长度(第4—5字节),消息体(消息体长度个字节)
(1)client_hello
客户端发起请求,以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数,扩展字段等信息,相关信息如下:
支持的最高TSL协议版本version,从低到高依次 SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2,当前基本不再使用低于 TLSv1 的版本;客户端支持的加密套件 cipher suites 列表, 每个加密套件对应前面 TLS 原理中的四个功能的组合:认证算法 Au (身份验证)、密钥交换算法 KeyExchange(密钥协商)、对称加密算法 Enc (信息加密)和信息摘要 Mac(完整性校验);支持的压缩算法 compression methods 列表,用于后续的信息压缩传输;随机数 random_C,用于后续的密钥的生成;扩展字段 extensions,支持协议与算法的相关参数以及其它辅助信息等,常见的 SNI 就属于扩展字段,后续单独讨论该字段作用。(2).server_hello+server_certificate+sever_hello_done
server_hello, 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 等,其中随机数用于后续的密钥协商;server_certificates, 服务器端配置对应的证书链,用于身份验证与密钥交换;server_hello_done,通知客户端 server_hello 信息发送结束;(3).证书校验
[证书链]的可信性 trusted certificate path,方法如前文所述;证书是否吊销 revocation,有两类方式离线 CRL 与在线 OCSP,不同的客户端行为会不同;有效期 expiry date,证书是否在有效时间范围;域名 domain,核查证书域名是否与当前的访问域名匹配,匹配规则后续分析;(4).client_key_exchange+change_cipher_spec+encrypted_handshake_message
client_key_exchange,合法性验证通过之后,客户端计算产生随机数字 Pre-master,并用证书公钥加密,发送给服务器;此时客户端已经获取全部的计算协商密钥需要的信息:两个明文随机数 random_C 和 random_S 与自己计算产生的 Pre-master,计算得到协商密钥;enc_key=Fuc(random_C, random_S, Pre-Master)change_cipher_spec,客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信;encrypted_handshake_message,结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商密钥 session secret 与算法进行加密,然后发送给服务器用于数据与握手验证;(finished,校验摘要信息?)
(5).change_cipher_spec+encrypted_handshake_message
服务器用私钥解密加密的 Pre-master 数据,基于之前交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key=Fuc(random_C, random_S, Pre-Master);计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性;change_cipher_spec, 验证通过之后,服务器同样发送 change_cipher_spec 以告知客户端后续的通信都采用协商的密钥与算法进行加密通信;encrypted_handshake_message, 服务器也结合所有当前的通信参数信息生成一段数据并采用协商密钥 session secret 与算法加密并发送到客户端;(finished,校验摘要信息?)(6).握手结束
客户端计算所有接收信息的 hash 值,并采用协商密钥解密 encrypted_handshake_message,验证服务器发送的数据和密钥,验证通过则握手完成;
(7).加密通信
开始使用协商密钥与算法进行加密通信。
这是之前研究的流程,也放在这里好了。
1,浏览器将自己支持的一套加密规则发送给服务器端,如RSA加密算法,DES对称加密算法,SHA1摘要算法。
2,服务器从中选出一组加密算法与HASH算法,并将证书发给浏览器。证书内容包括了网站地址,加密公钥等等。在握手的整个过程中,都用到了证书中的公钥和浏览器发送给服务器的随机密码以及加密算法。(证书的内容解析打印出来是一长串字节,数字与字母的组合。客户端发送过来的随机数解析打印出来也是一长串字节,数字与字母的组合)
3,客户端拿到证书以后。
验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。 使用约定好的HASH算法计算握手消息(如SHA1),并使用生成的随机数对消息进行加密,最后将之前生成的被公钥加密的随机数密码,HASH摘要值一起发送给服务器。4,服务器收到客户端发来的数据以后。
使用自己的私钥将信息解密并取出浏览器发送给服务器的随机密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。使用随机密码加密一段握手消息,发送给浏览器。
5,浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
服务端启用以Tomcat为例,需要三步:创建keystore文件(保存了私钥和公钥);配置Tomcat SSL连接器;创建客户端需要使用的电子证书。
获去证书需要走以下几步:
服务端人员需要使用keystore生成一个Certificate Signing Requst(csr文件)。服务端人员把CSR文件发送给一个合法的CA机构,然后由CA机构生成一个证书。服务端人员把证书下下来,然后部署到服务器中。SSL基于信任链来验证站点证书的合法性,所以,你还要有一个CA的根证书,这个证书也需要从CA下载。把从CA下载的根证书和你通过CSR文件获取的证书一起导入你的keystore。
客户端访问
客户端往服务端发送加密数据,首先得需要获得公钥,这个公钥在保存在CA提供的证书中,所以客户端首先得下载一个证书文件(一般是用户代理自动下载)。
客户端使用证书时,SSL会发送一个请求到证书中所指定的CA再次确认你的证书确实是从CA获取的,而不是自己创建的。客户端还可以验证服务端是否确实是自己调用的服务端。这两步构成了Peer Authentication。
服务端任务1,获取客户端发送的支持的加密算法,包括hash算法。
2,发送证书给客户端,(就是用流写字节)
3,获取客户端通过公钥加密后的随机数,(就是流读字节)
4,私钥解密公钥加密后的随机数,得到解密后的随机密码。
5,获取客户端加密消息,(还是流读取字节)
6,用私钥对消息解密(带随机数)
7,解密出来数据后,采用约定的hash算法计算其hash值。
8,获取客户端发送过来的hash值,比较计算出来的hash值,是否一致。以判断信息是否完整,是否被篡改。
9,如果第一次校验客户端发送过来的消息和摘要一致,服务器就开始向客户端发送消息和摘要。
10,根据指定的算法和之前客户端发送过来的随机密码(已解密的),生成密钥。
11,用生成的密钥加密发送给客户端的数据,发送给客户端;用hash算法计算要发送给客户端的数据的hash值,发送给客户端,
客户端任务1,客户端发送自己支持的hash算法
2,客户端验证服务器端证书是否合法
3,从证书里面获取公钥
4,生成随机密码,公钥加密随机密码,发送给服务器。
5,使用公钥和随机密码加密发送到服务器的数据,发送给服务器。
5,使用hash算法计算发送到服务器的数据的hash值,发送给服务器。
6,接收服务器的数据。
7,公钥,随机密码解密数据。
8,接收服务器的摘要信息。根据约定的hash算法,计算接收的数据的hash值,对比是否一致。
证书没有经过认证的证书是不被浏览器信任的,所以当访问的时候回提示不安全的网站,需要点击信任之后才能继续访问。
而经过认证的证书会提示安全,如下
证书格式(是一种标准):
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,扩展名无关)可以通过Java原生工具——KeyTool生成;而后者PKCS#12文件(通常为.p12或.pfx,意味个人信息交换文件),则是通过更为常用的OpenSSL工具产生。
pfx转keystorekeytool -importkeystore -v -srckeystore jiaohangtest.pfx -srcstoretype pkcs12 -srcstorepass 111111 -destkeystore jiaohangtest.keystore -deststoretype jks -deststorepass 111111
-importkeystore导入密钥库,通过格式设定,我们可以将PKCS#12文件转换为JKS格式。
-v显示详情
-srckeystore源密钥库,这里是jiaohangtest.pfx
-srcstoretype源密钥库格式,这里为pkcs12
-srcstorepass源密钥库密码,这里为111111
-destkeystore目标密钥库,这里为jiaohangtest.keystore
-deststoretype目标密钥库格式,这里为jks,默认值也如此
-deststorepass目标密钥库密码,这里为111111
通过这个操作,我们能够获得所需的密钥库文件zlex.keystore。
keytool -list -keystore jiaohangtest.keystore -storepass 111111 -v
-list列举密钥库
-keystore密钥库,这里是jiaohangtest.keystore
-storepass密钥库密码,这里是111111
-v显示详情
导出证书
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
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 !!!! PKCS12alias !!!! [{3ff077c0-db58-4a2c-90d7-010189f6cefb}]is key entry !!!! truecert class !!!! sun.security.x509.X509CertImplcert !!!! [[ 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=falseAuthorityInfoAccess [ [ accessMethod: ocsp accessLocation: URIName: http://ocsptest.cfca.com.cn:80/ocsp]][2]: ObjectId: 2.5.29.35 Criticality=falseAuthorityKeyIdentifier [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=trueBasicConstraints:[ CA:false PathLen: undefined][4]: ObjectId: 2.5.29.31 Criticality=falseCRLDistributionPoints [ [DistributionPoint: [URIName: http://210.74.42.3/OCA31/RSA/crl39.crl]]][5]: ObjectId: 2.5.29.37 Criticality=falseExtendedKeyUsages [ clientAuth emailProtection][6]: ObjectId: 2.5.29.15 Criticality=trueKeyUsage [ DigitalSignature Non_repudiation][7]: ObjectId: 2.5.29.14 Criticality=falseSubjectKeyIdentifier [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..d0030: 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.\z0050: 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,&.....N00C0: 72 85 7B 68 AA 6D FC DA B6 08 5E ED 26 8B 44 7A r..h.m....^.&.Dz00D0: 5A BB 2F 69 7B 64 60 67 06 16 75 DB D1 0D 3D 54 Z./i.d`g..u...=T00E0: 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: 65537private key !!!! sun.security.rsa.RSAPrivateCrtKeyImpl@ffa5f146
加密:公钥放在客户端,并使用公钥对数据进行加密,服务端拿到数据后用私钥进行解密;
加签:私钥放在客户端,并使用私钥对数据进行加签,服务端拿到数据后用公钥进行验签。
前者完全为了加密;后者主要是为了防恶意***,防止别人模拟我们的客户端对我们的服务器进行***,导致服务器瘫痪。
不管是客户端还是服务端,都要存以下两样keystore。
KeyStore:保存自己的公钥和私钥。
Trust KeyStore:保存对方的公钥证书。
是客户端信任服务端,
服务器端的KeyStore存储自己的公钥和私钥,客户端的Trust KeyStore要导入服务器端的公钥证书。
双向认证是客户端既要信任服务端而且服务端也要信任客户端。
服务器端的KeyStore存储自己的公钥和私钥,客户端的Trust KeyStore要导入服务器端的公钥证书。
客户端的KeyStore存储自己的公钥和私钥,服务器端的Trust KeyStore要导入客户端的公钥证书。
加密/解密对称加密算法DES就是加密和解密都是用同一个秘钥,这种方式优点就是速度快,缺点就是在管理和分配秘钥的时候不安全。
(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。
AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高;
非对称加密算法RSA算法非对称加密有一个秘钥对,叫做公钥和私钥,私钥自己持有,公钥可以公开的发送给使用的人。使用公钥进行加密的信息,只有和其配对的私钥可以解开。使用私钥钥进行加密的信息,只有和其配对的公钥可以解开。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
由 RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的; RSA是第一个也是目前唯一一个既能用于密钥交换又能用于数字签名的算法。
DSA
(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);
ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学。
综合一般都是对称加密和非对称加密结合使用,使用非对称加密完成秘钥的传递,然后使用对称秘钥进行数据加密和解密。比如RSA非对称加密,对加密的内容有长度限制,长度过长就不行。
加签/验签哈希算法
MD4抗篡改能力,通常用于文件校验,数字签名,鉴权协议。
加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。
只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。而且只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息。
(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。其输出为 128 位。MD4 已证明不够安全。
MD5(RFC 1321)是 Rivest 于1991年对 MD4 的改进版本。它对输入仍以 512 位分组,其输出是 128 位。MD5 比 MD4 复杂,并且计算速度要慢一点,更安全一些。MD5 已被证明不具备”强抗碰撞性”。
SHA(Secure Hash Algorithm)是一个 Hash 函数族,由 NIST(National Institute of Standards and Technology)于 1993 年发布第一个算法。目前知名的 SHA-1 在 1995 年面世,它的输出为长度 160 位的 hash 值,因此抗穷举性更好。SHA-1 设计时基于和 MD4 相同原理,并且模仿了该算法。SHA-1 已被证明不具”强抗碰撞性”。
为了提高安全性,NIST 还设计出了 SHA-224、SHA-256、SHA-384,和 SHA-512 算法(统称为 SHA-2),跟 SHA-1 算法原理类似。SHA-3 相关算法也已被提出。
Java安全套接扩展 (Java Secure Socket Extension, JSSE)是实现Internet安全通信的一系列包的集合。它是一个SSL和TLS的纯Java实现。
TrustManager接口JSSE中,有一个信任管理器类负责决定是否信任远端的证书;一般的,仅会有一个支持基于X.509(数字证书标准)公钥认证的TrustManager。
如果系统属性javax.net.sll.trustStore指定了TrustStore文件(客户端的TrustStore文件中保存着被客户端所信任的服务器的证书信息),那么信任管理器就去jre安装路径下的lib/security/目录中寻找并使用这个文件来检查证书。
如果该系统属性没有指定TrustStore文件,它就会去jre安装路径下寻找默认的TrustStore文件,这个文件的相对路径为:lib/security/jssecacerts。
如果 jssecacerts不存在,但是cacerts存在(它随J2SDK一起发行,含有数量有限的可信任的基本证书),那么这个默认的TrustStore文件就是cacerts。直接使用类HttpsURLConnection访问Web页面,如果站点的安全证书不被JSSE所信任,访问就报错,如果站点的证书被JSEE内置信任就访问OK。
对于不被JSSE所默认信任的,一种解决方法是把站点的证书放到证书库文件jssecacerts中, 或者把证书存放到任一TrustStore文件中,然后设置系统属性javax.net.sll.trustStore指向该文件。另一种解决方法则是自己实现信任管理器类,让它信任我们指定的证书。
1,将证书导入到TrustStore文件中
Java提供了命令行工具keytool用于创建证书或者把证书从其它文件中导入到Java自己的TrustStore文件中。
取得源证书文件,把这个文件复制到jre安装路径下的lib/security/目录中。这样,只需在程序中设置系统属性javax.net.sll.trustStore指向文件dest_cer_store,就能使JSSE信任该证书,从而使程序可以访问使用未经验证的证书的HTTPS站点。
使用这种方法,编程非常简单,但需要手工导出服务器的证书。当服务器证书经常变化时,就需要经常进行手工导出证书的操作。
2,X509证书信任管理器类的实现及应用
进行SSL的验证或者过滤之后才能够访问。
package com.lgx.http;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import javax.net.ssl.X509TrustManager;/** 在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。 我们可以自己实现该接口,让它信任我们指定的证书。 当方法为空是默认为所有的链接都为安全,也就是所有的链接都能够访问到。 接口X509TrustManager有下述三个公有的方法需要我们实现:**/public class MyX509TrustManager implements X509TrustManager { /* 该方法检查客户端的证书,若不信任该证书则抛出异常。 由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。 JSSE中,默认的信任管理器类为TrustManager。 */ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } /* 该方法检查服务器的证书,若不信任该证书同样抛出异常。 通过自己实现该方法,可以使之信任我们指定的任何证书。 可以不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。 */ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } /* 返回受信任的X509证书数组。 */ 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请求 请求地址、请求方法、参数 */ public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) { StringBuffer buffer = null; try { // 1,创建SSLContext,并使用我们指定的信任管理器初始化 SSLContext sslContext = SSLContext.getInstance("SSL"); TrustManager[] tm = { new MyX509TrustManager() }; sslContext.init(null, tm, new java.security.SecureRandom()); // 2,获取SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); // 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象 URL url = new URL(requestUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); //属性设置 conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod(requestMethod); // 设置当前实例使用的SSLSoctetFactory,12只和这一步有关。 conn.setSSLSocketFactory(ssf); //连接 conn.connect(); // 往服务器端写内容 if (null != outputStr) { OutputStream os = conn.getOutputStream(); os.write(outputStr.getBytes("utf-8")); os.close(); } // 读取服务器端返回的内容 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接口
决定将哪一个认证证书发送给对端服务器,单向认证,就会传一个null,
完整代码实现读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(); // 构建签名 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); } // 服务器验签,自己证书的公钥 public boolean CheckSignature(String data, String sign) { boolean flag = true; ReadKeystore readKeystore = new ReadKeystore(); // 获得证书 X509Certificate x509Certificate = (X509Certificate) readKeystore .certificateFormKeystore(); // 获得公钥 PublicKey publicKey = x509Certificate.getPublicKey(); // 构建签名 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 { // 本地加密,服务器的公钥 public String encryptDate(String data) throws Exception { byte[] encryptByte = null; ReadKeystore readKeystore = new ReadKeystore(); // 取得公钥 PublicKey publicKey = readKeystore.publicKeyFormKeystore(); // 对数据加密 Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); encryptByte = cipher.doFinal(data.getBytes()); return Base64.encode(encryptByte); } // 服务器解密,服务器的私钥 public String decryptDate(String data) throws Exception { byte[] decryptByte = null; // 取得私钥 ReadKeystore readKeystore = new ReadKeystore(); PrivateKey privateKey = readKeystore.privateKeyFormKeystore(); // 对数据解密 Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); decryptByte = cipher.doFinal(data.getBytes()); return Base64.encode(decryptByte); }}
数据加密解密
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 { // 本地加密,服务器的公钥 public String encryptDate(String data) throws Exception { byte[] encryptByte = null; ReadKeystore readKeystore = new ReadKeystore(); // 取得公钥 PublicKey publicKey = readKeystore.publicKeyFormKeystore(); // 对数据加密 Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); encryptByte = cipher.doFinal(data.getBytes()); return Base64.encode(encryptByte); } // 服务器解密,服务器的私钥 public String decryptDate(String data) throws Exception { byte[] decryptByte = null; // 取得私钥 ReadKeystore readKeystore = new ReadKeystore(); PrivateKey privateKey = readKeystore.privateKeyFormKeystore(); // 对数据解密 Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); decryptByte = cipher.doFinal(data.getBytes()); return Base64.encode(decryptByte); }}
校验服务器证书
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()); } // 设置通用的请求属性 // 发送POST请求必须设置如下两行 connection.setDoOutput(true); connection.setDoInput(true); // 设置接收数据的格式 connection.setRequestProperty("Accept", "*/*"); connection.setRequestProperty("OriI***Id", "C1030131001288"); connection.setRequestProperty("MsgTP", "uops.010.000.01"); // 设置维持长连接 connection.setRequestProperty("Connection", "Keep-Alive"); connection.setRequestProperty("Accept-Encoding", "gzip"); // 设置文件字符集: connection.setRequestProperty("Charset", "UTF-8"); // 设置发送数据的格式 connection.setRequestProperty("Content-Type", "application/json"); // 设置不用缓存,注意设置请求方法为post不能用缓存 connection.setUseCaches(false); // 设置传递方式 connection.setRequestMethod("POST"); // 开始连接请求 connection.connect(); // 获取URLConnection对象对应的输出流 out = new PrintWriter(connection.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 读取URL的响应,返回的流。如果有错误,返回错误的信息 if (connection.getResponseCode() == 200) { in = new BufferedReader(new InputStreamReader(connection .getInputStream(), "UTF-8")); } else { in = new BufferedReader(new InputStreamReader(connection .getErrorStream(), "UTF-8")); } // 转字符串 String content = ""; while ((content = in.readLine()) != null) { result += content; } } 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(); } } System.out.println(("getDataFromServer:" + result)); return result; } public SSLContext getSSLContext() throws Exception { long time1 = System.currentTimeMillis(); if (sslContext == null) { try { // 服务器要验证客户端证书 KeyManagerFactory keyManagerFactory = KeyManagerFactory .getInstance("SunX509"); ReadKeystore readKeystore = new ReadKeystore(); KeyStore keyStore = readKeystore.keyStoreFromKeystore(); keyManagerFactory.init(keyStore, KEY_STORE_PASS.toCharArray()); KeyManager[] keyManagers = keyManagerFactory.getKeyManagers(); // 客户端要验证服务端证书 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); }}
测试过程中问题
经过代理服务器连接的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;/* * 经过代理服务器后,由代理服务器走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); // 我自己的代理服务器 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()); // 传参数 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());}
经过投产,代码稳定运行两年
拓展网络协议声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。