├── client.crt ├── client.csr ├── client.go ├── client.key ├── client.pfx ├── client_single.go ├── readme.md ├── res ├── 1.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 17.png ├── 18.png ├── 19.png ├── 2.png ├── 20.png ├── 21.png ├── 22.png ├── 23.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── root.crt ├── root.csr ├── root.key ├── root.srl ├── server.crt ├── server.csr ├── server.go ├── server.key └── server_single.go /client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDTDCCAjQCCQCrw+G01/SJNzANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJD 3 | TjERMA8GA1UECAwIU2hhbmRvbmcxEDAOBgNVBAcMB1FpbmdkYW8xITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNTEyMDcwODIzNTJaFw0xNjEy 5 | MDYwODIzNTJaMHsxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZG9uZzEQMA4G 6 | A1UEBwwHUWluZ2RhbzENMAsGA1UECgwEU0taSDETMBEGA1UEAwwKZmx5aW5ndGlt 7 | ZTEjMCEGCSqGSIb3DQEJARYUZmx5aW5ndGltZWljZUAxNi5jb20wggEiMA0GCSqG 8 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5wLZYh2clloRQRTWVL7RAxLInnlKo7z7H 9 | guH4vPJGCfEN6a4vVYfSaOsvKVt/GiaYc94t1Gomopt6MJ0SgiyNuBPaHteFF0Vq 10 | krzg/aKoFYOQcVY7yMEj9WoNt1t207w9NyzPzQ1NLQ5T6GwIQ0AJB12Wg0l8QCmg 11 | jMX4JMBkrJuv0IJnsjV4zlzuPtt1s8BlvZnx3JmNP2P31EF1pONDHnN3LB1i9JTM 12 | hTWfl22YAvKQbI9xRJtK74eqx7di9qLofVSl4uUcbuiYL5qVQJterRDYVgY53dzt 13 | dmSFUy9hJ6SR7e2Kizbqf99ukplDdFDBZ7ebnXzZJowZ9NRJ+EHBAgMBAAEwDQYJ 14 | KoZIhvcNAQELBQADggEBAKu3UgQ9qWcBNpBjlDYNOQfP5SWenfb59L9heCBl0YSE 15 | z5MnaJmblUiw8jQJjHYaCM/cZFG84Edqr7r5cu2YA+gzBKm0hvHFFpaGPXskfSsK 16 | MtrARpFfm2PE0oXhV4sSWJPuLH5mhBUXW28qFmTNn3aliI7JL3rtaLb+twmgwjYK 17 | trcncrFod3cSjbLoS3fpZXS/yVM4JUmDGKdUg/IfdB8jclem6Iwbhjd9umOP26jB 18 | 0mnTbcMKbQF+2bsfKVMhjwwLsHqZ3eKmYvKX3otlM6SHwsBzh5vntjUFQ5nfEitX 19 | ZWWwfBwxT/7V0VLAoVIYFUevWbyvzKOut/NchHZZdAA= 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICwDCCAagCAQAwezELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoYW5kb25nMRAw 3 | DgYDVQQHDAdRaW5nZGFvMQ0wCwYDVQQKDARTS1pIMRMwEQYDVQQDDApmbHlpbmd0 4 | aW1lMSMwIQYJKoZIhvcNAQkBFhRmbHlpbmd0aW1laWNlQDE2LmNvbTCCASIwDQYJ 5 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBALnAtliHZyWWhFBFNZUvtEDEsieeUqjv 6 | PseC4fi88kYJ8Q3pri9Vh9Jo6y8pW38aJphz3i3Uaiaim3ownRKCLI24E9oe14UX 7 | RWqSvOD9oqgVg5BxVjvIwSP1ag23W3bTvD03LM/NDU0tDlPobAhDQAkHXZaDSXxA 8 | KaCMxfgkwGSsm6/QgmeyNXjOXO4+23WzwGW9mfHcmY0/Y/fUQXWk40Mec3csHWL0 9 | lMyFNZ+XbZgC8pBsj3FEm0rvh6rHt2L2ouh9VKXi5Rxu6JgvmpVAm16tENhWBjnd 10 | 3O12ZIVTL2EnpJHt7YqLNup/326SmUN0UMFnt5udfNkmjBn01En4QcECAwEAAaAA 11 | MA0GCSqGSIb3DQEBCwUAA4IBAQCNHA/sYlMKfAQpC44vsajk5pueNZD7rSrLw25D 12 | GKC7iE41aET9mrjHMmP9o8wH65LuSh5QLq26qhMYAx0yVZkX7fF5AJukBsW9kr3A 13 | XLCuUZ1DTSvQgRaltqUtihxOAIgnod8wKtTdQt5VeS+HFsLmpIPlbRo/ZjDp46z5 14 | Ofr+B+DD8Xv9Pmo22fAMk8MWHB0WqBNUQjbNKVthl/DVGOi6nSdhhew/2I6fw50L 15 | vgxtyQkPJsxwCVcuwsvw5v1kBXF1KPsqERLepJnRmF++JpNliiVr6v2XJYPJjxwV 16 | 3Tp30q4voONJhch2Lk9IssYGL+1dqPOj+XLy7Z/AKo2s2jvG 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | ) 10 | 11 | func main() { 12 | pool := x509.NewCertPool() 13 | caCertPath := "root.crt" 14 | 15 | caCrt, err := ioutil.ReadFile(caCertPath) 16 | if err != nil { 17 | log.Fatal("ReadFile err:", err) 18 | return 19 | } 20 | pool.AppendCertsFromPEM(caCrt) 21 | 22 | cliCrt, err := tls.LoadX509KeyPair("client.crt", "client.key") 23 | if err != nil { 24 | log.Fatal("LoadX509KeyPair err:", err) 25 | return 26 | } 27 | 28 | tr := &http.Transport{ 29 | TLSClientConfig: &tls.Config{ 30 | RootCAs: pool, 31 | Certificates: []tls.Certificate{cliCrt}, 32 | }, 33 | } 34 | client := &http.Client{Transport: tr} 35 | resp, err := client.Get("https://localhost:8080") 36 | if err != nil { 37 | log.Fatal("client error:", err) 38 | return 39 | } 40 | defer resp.Body.Close() 41 | body, err := ioutil.ReadAll(resp.Body) 42 | log.Println(string(body)) 43 | } 44 | -------------------------------------------------------------------------------- /client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAucC2WIdnJZaEUEU1lS+0QMSyJ55SqO8+x4Lh+LzyRgnxDemu 3 | L1WH0mjrLylbfxommHPeLdRqJqKbejCdEoIsjbgT2h7XhRdFapK84P2iqBWDkHFW 4 | O8jBI/VqDbdbdtO8PTcsz80NTS0OU+hsCENACQddloNJfEApoIzF+CTAZKybr9CC 5 | Z7I1eM5c7j7bdbPAZb2Z8dyZjT9j99RBdaTjQx5zdywdYvSUzIU1n5dtmALykGyP 6 | cUSbSu+Hqse3Yvai6H1UpeLlHG7omC+alUCbXq0Q2FYGOd3c7XZkhVMvYSekke3t 7 | ios26n/fbpKZQ3RQwWe3m5182SaMGfTUSfhBwQIDAQABAoIBAFesiySr/FZ0fc05 8 | bXoWAxlS/dfPVaqhCdu3fhsea6f9R0bO1kVHNI1ushsXhTUvzanFfsfY66WCuKnq 9 | yiiTQp49lTktt4H9IumTiw0TCjQVu3xw0kfzkJ39VupUchpbBA1MvpzyZuXXb1zR 10 | ZjRcMZxRWq4RF51K15sM9uAR0LFzLSo8p+NZvndiKyVni5F8mWTfepEwjtjfoG5/ 11 | RIRzW9c/wuxmbQq/lvSk+tnnH6wQ5xqXpxhytZ4C3UW/MGGrjfRN4nxag1RMGPwI 12 | qismBZNc35E/822ogmu0kUMvEgyqde8KSs1K2N2483x1CYMI1NFTkBbYduP2z46K 13 | MkV+RXECgYEA4cgFpQS2sMGvOSt0Q+xl+Zda0YxC6nSkNkbTIQf8YgaemTiQjXdw 14 | opw3A7X+y9PWXbWGbeBhCBRctJaZkjbcH53lEgN/eIu+HNXyZPv9UXxO6Pt4DTzO 15 | DcRJIsYy27RKWbj+e4k6oK2M2W1WhLff4BV6fm4iVnAJ0FrdUjccbf0CgYEA0p0v 16 | rFGIFCUP+Uiy5erotBDGz4I3sCj/NRbPMp8ImDBUK623utiMy6VJW5MYn30lKjDF 17 | sSUFlrMdRUPtvZ3Qz3Km1gKv9nPP8bxqbXAlduCeK7fk5Ns67SBUc7Xnc9zT3o+K 18 | 1f2G/d1ljXhyCAxGvQpvU33m9GuY9ZnJL6GW7BUCgYEArkw810yRQFj1TTwXkEwR 19 | 2SGX8cbG7bpH/sKkQI6qrn4Pt5csOJmpMU9JRSsdXPrXNRZqha4/Gf6mJp9QRMjn 20 | G91HtqVOpZ+zjw03B/BkeaBuRnvDDO0Q4R3Tm+3H20YOU791babdxKbV4g//R4uv 21 | X40VOD8LcREi8l8DFnIHF30CgYADxQZ2ahsqaSNpDdEN5m910ZsNWcJPZ9xxgdAB 22 | kvEfcDYBdiGEuZ2Dg5jVh8N4D1Bb+fV/3y7DbL9IXxfhPfLf06iCyheGLLp7FCk/ 23 | fjNddlW+aJMzOW1LkzmPvKDA5SHxqNYOUHRbFNxddNtto3KcrZQihW1d0JMzSiZc 24 | sOK3pQKBgFJ0cKfZcl8df4ukEnBDniVQ5Zzbul3Y/Y33XaEz1vsXgdVq/Hf26GVg 25 | rkqeMcII9KuW7Qp6/VYPD9Z/+dk5N0oYlol//z3jpe3GJ8LZHv7AXfWKJhOSeDqr 26 | X0VOd4Jx3xFdw7Z2UGnTctipucdNjpjLyw01WNfLUHHKriEjfhoH 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /client.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/client.pfx -------------------------------------------------------------------------------- /client_single.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | ) 10 | 11 | func main() { 12 | pool := x509.NewCertPool() 13 | caCertPath := "root.crt" 14 | 15 | caCrt, err := ioutil.ReadFile(caCertPath) 16 | if err != nil { 17 | log.Fatal("ReadFile err:", err) 18 | return 19 | } 20 | pool.AppendCertsFromPEM(caCrt) 21 | 22 | tr := &http.Transport{ 23 | TLSClientConfig: &tls.Config{RootCAs: pool}, 24 | } 25 | client := &http.Client{Transport: tr} 26 | resp, err := client.Get("https://localhost:8080") 27 | if err != nil { 28 | log.Fatal("client error:", err) 29 | return 30 | } 31 | defer resp.Body.Close() 32 | body, err := ioutil.ReadAll(resp.Body) 33 | log.Println(string(body)) 34 | } 35 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # GOLANG搭建单、双向自认证HTTPS服务器 2 | ### 前言 3 | >2015年双11期间淘宝、天猫实现了全站式https安全传输,web安全问题已经成了人们关注的话题,那什么是https呢?如何实现单、双向自认证https服务器呢?接下来我们将一一介绍。 4 | 5 | ## 一、HTTPS相关概念已经认证流程 6 | ###### 基本概念: 7 | [**HTTPS**](http://baike.baidu.com/link?url=XuEFqp8HTAIWBO12QMzj54K1iIBGPL6VJGPEn85nyCirdG8LE104hMYvOeDgfucyMf3gu1zPLap3i0BKb-SKHa)(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。关于https详细介绍请见:[大型网站的HTTPS实践](http://studygolang.com/articles/2984)。 8 | 9 | **SSL**(Secure Socket Layer):是Netscape公司设计的主要用于WEB的安全传输协议。从名字就可以看出它在https协议栈中负责实现上面提到的加密层。 10 | 11 | **数字证书**:一种文件的名称,好比一个机构或人的签名,能够证明这个机构或人的真实性。其中包含的信息,用于实现上述功能。 12 | 13 | **加密和认证**:加密是指通信双方为了防止敏感信息在信道上被第三方窃听而泄漏,将明文通过加密变成密文,如果第三方无法解密的话,就算他获得密文也无能为力;认证是指通信双方为了确认对方是值得信任的消息发送或接受方,而不是使用假身份的非法者,采取的确认身份的方式。只有同时进行了加密和认证才能保证通信的安全,因此在SSL通信协议中这两者都被应。早期一般是用对称加密算法,现在一般都是不对称加密,最常见的算法就是RSA。 14 | 15 | **消息摘要**:这个技术主要是为了避免消息被篡改。消息摘要是把一段信息,通过某种算法,得出一串字符串。这个字符串就是消息的摘要。如果消息被篡改(发生了变化),那么摘要也一定会发生变化(如果2个不同的消息生成的摘要是一样的,那么这就叫发生了碰撞)。消息摘要的算法主要有MD5和SHA,在证书领域,一般都是用SHA(安全哈希算法)。 16 | 17 | 数字证书、加密和认证、消息摘要三个技术结合起来,就是在HTTPS中广泛应用的证书(certificate),证书本身携带了加密/解密的信息,并且可以标识自己的身份,也自带消息摘要。 18 | ###### HTTPS认证过程: 19 | 1. 浏览器发送一个连接请求给安全服务器。 20 | 2. 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。 21 | 3. 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。 22 | 4. 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。 23 | 5. 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。 24 | 6. 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。 25 | 7. 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。 26 | 8. 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。 27 | 9. 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。 28 | 10. 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。 29 | 30 | 上面所述的是双向认证 SSL 协议的具体通讯过程,这种情况要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有 CA 证书,具体的过程相对于上面的步骤,只需将服务器端验证客户证书的过程去掉,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的 (这并不影响 SSL 过程的安全性)密码方案。这样,双方具体的通讯内容,就是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密 的数据进行解密,这时候的安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使用128 位加密通讯的原因。 31 | ## 二、自认证根证书 32 | 1. 创建根证书密钥文件(自己做CA)root.key: 33 | 34 | ``` shell 35 | $openssl genrsa -des3 -out root.key 2048 36 | ``` 37 | 38 | 需要输入两次私钥密码 39 | ![](/res/1.png) 40 | 2. 创建根证书的申请文件root.csr: 41 | 42 | ``` shell 43 | $openssl req -new -key root.key -out root.csr 44 | ``` 45 | 46 | 输入root.key的密码 47 | ![](/res/2.png) 48 | 49 | 3. 创建根证书root.crt: 50 | 51 | ``` shell 52 | $openssl x509 -req -days 3650 -sha256 -extensions v3_ca -signkey root.key -in root.csr -out root.crt 53 | ``` 54 | 55 | 生成根证书 56 | ![](/res/3.png) 57 | 58 | ## 三、SSL单向认证 59 | 1. 创建服务器证书秘钥 60 | 61 | ``` shell 62 | $openssl genrsa –des3 -out server.key 2048 63 | ``` 64 | 65 | 需要输入两次私钥密码 66 | ![](/res/4.png) 67 | 2. 去除key口令 68 | 69 | ``` shell 70 | $openssl rsa -in server.key -out server.key 71 | ``` 72 | 73 | 需要输入私钥密码 74 | ![](/res/5.png) 75 | 3. 创建服务器证书申请文件server.csr 76 | 77 | ``` shell 78 | $openssl req -new -key server.key -out server.csr 79 | ``` 80 | 81 | "Common Name"最好跟网站的域名一致 82 | ![](/res/6.png) 83 | 4. 创建服务器证书server.crt 84 | 85 | ``` shell 86 | $openssl x509 -req -days 365 -sha256 -extensions v3_req -CA root.crt -CAkey root.key -CAcreateserial -in server.csr -out server.crt 87 | ``` 88 | 89 | 需要输入根私钥密码 90 | ![](/res/7.png) 91 | 92 | 5. 客户端导入根证书并添加到“信任的根服务站点” 93 | ![](/res/8.png) 94 | ![](/res/9.png) 95 | ![](/res/10.png) 96 | ![](/res/11.png) 97 | ![](/res/12.png) 98 | ![](/res/13.png) 99 | ![](/res/14.png) 100 | ![](/res/15.png) 101 | 6. golang实现简单的https服务器 102 | 103 | ``` Go 104 | package main 105 | 106 | import ( 107 | "io" 108 | "log" 109 | "net/http" 110 | ) 111 | 112 | func handler(w http.ResponseWriter, r *http.Request) { 113 | io.WriteString(w, "golang https server") 114 | } 115 | 116 | func main() { 117 | http.HandleFunc("/", handler) 118 | if err := http.ListenAndServeTLS(":8080", "server.crt", "server.key", nil); err != nil { 119 | log.Fatal("ListenAndServe:", err) 120 | } 121 | } 122 | 123 | ``` 124 | 125 | 7. 在浏览器中测试 126 | ![](/res/16.png) 127 | 128 | ## 四、SSL双向认证 129 | 在单向认证的基础上添加客户端证书并在golang服务器源码上添加客户端认证相关代码 130 | 131 | 1. 创建客户端证书私钥 132 | 133 | ``` shell 134 | $openssl genrsa -des3 -out client.key 2048 135 | ``` 136 | 137 | 需要输入两次私钥密码 138 | ![](/res/17.png) 139 | 2. 去除key口令 140 | 141 | ``` shell 142 | $openssl rsa -in client.key -out client.key 143 | ``` 144 | 145 | 需要输入私钥密码 146 | ![](/res/18.png) 147 | 3. 创建客户端证书申请文件client.csr 148 | 149 | ``` shell 150 | $openssl req -new -key client.key -out client.csr 151 | ``` 152 | 153 | ![](/res/19.png) 154 | 155 | 3. 创建客户端证书文件client.crt 156 | 157 | ``` shell 158 | $openssl x509 -req -days 365 -sha256 -extensions v3_req -CA root.crt -CAkey root.key -CAcreateserial -in client.csr -out client.crt 159 | ``` 160 | 161 | ![](/res/20.png) 162 | 4. 将客户端证书文件client.crt和客户端证书密钥文件client.key合并成客户端证书安装包client.pfx 163 | 164 | ``` shell 165 | $openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx 166 | ``` 167 | 168 | 设置客户端安装时的密码 169 | ![](/res/23.png) 170 | 2. 添加客户端证书 171 | 172 | 参见服务器端添加证书,客户端证书添加到“个人”里面就可以 173 | ![](/res/21.png) 174 | 3. 修改服务器代码 175 | 176 | ``` Go 177 | package main 178 | 179 | import ( 180 | "crypto/tls" 181 | "crypto/x509" 182 | "io" 183 | "io/ioutil" 184 | "log" 185 | "net/http" 186 | ) 187 | 188 | type httpsHandler struct { 189 | } 190 | 191 | func (*httpsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 192 | io.WriteString(w, "golang https server!!!") 193 | } 194 | 195 | func main() { 196 | pool := x509.NewCertPool() 197 | caCertPath := "root.crt" 198 | 199 | caCrt, err := ioutil.ReadFile(caCertPath) 200 | if err != nil { 201 | log.Fatal("ReadFile err:", err) 202 | return 203 | } 204 | pool.AppendCertsFromPEM(caCrt) 205 | 206 | s := &http.Server{ 207 | Addr: ":8080", 208 | Handler: &httpsHandler{}, 209 | TLSConfig: &tls.Config{ 210 | ClientCAs: pool, 211 | ClientAuth: tls.RequireAndVerifyClientCert, 212 | }, 213 | } 214 | 215 | if err = s.ListenAndServeTLS("server.crt", "server.key"); err != nil { 216 | log.Fatal("ListenAndServeTLS err:", err) 217 | } 218 | } 219 | 220 | ``` 221 | 4. 在浏览器中测试 222 | ![](/res/22.png) 223 | 5. 使用golang访问https服务器 224 | 225 | ``` Go 226 | package main 227 | 228 | import ( 229 | "crypto/tls" 230 | "crypto/x509" 231 | "io/ioutil" 232 | "log" 233 | "net/http" 234 | ) 235 | 236 | func main() { 237 | pool := x509.NewCertPool() 238 | caCertPath := "root.crt" 239 | 240 | caCrt, err := ioutil.ReadFile(caCertPath) 241 | if err != nil { 242 | log.Fatal("ReadFile err:", err) 243 | return 244 | } 245 | pool.AppendCertsFromPEM(caCrt) 246 | 247 | cliCrt, err := tls.LoadX509KeyPair("client.crt", "client.key") 248 | if err != nil { 249 | log.Fatal("LoadX509KeyPair err:", err) 250 | return 251 | } 252 | 253 | tr := &http.Transport{ 254 | TLSClientConfig: &tls.Config{ 255 | RootCAs: pool, 256 | Certificates: []tls.Certificate{cliCrt}, 257 | }, 258 | } 259 | client := &http.Client{Transport: tr} 260 | resp, err := client.Get("https://localhost:8080") 261 | if err != nil { 262 | log.Fatal("client error:", err) 263 | return 264 | } 265 | defer resp.Body.Close() 266 | body, err := ioutil.ReadAll(resp.Body) 267 | log.Println(string(body)) 268 | } 269 | 270 | ``` 271 | 272 | ### 结语 273 | 希望通过这次实例能让大家更好的理解、应用https,谢谢观看。 274 | -------------------------------------------------------------------------------- /res/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/1.png -------------------------------------------------------------------------------- /res/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/10.png -------------------------------------------------------------------------------- /res/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/11.png -------------------------------------------------------------------------------- /res/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/12.png -------------------------------------------------------------------------------- /res/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/13.png -------------------------------------------------------------------------------- /res/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/14.png -------------------------------------------------------------------------------- /res/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/15.png -------------------------------------------------------------------------------- /res/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/16.png -------------------------------------------------------------------------------- /res/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/17.png -------------------------------------------------------------------------------- /res/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/18.png -------------------------------------------------------------------------------- /res/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/19.png -------------------------------------------------------------------------------- /res/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/2.png -------------------------------------------------------------------------------- /res/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/20.png -------------------------------------------------------------------------------- /res/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/21.png -------------------------------------------------------------------------------- /res/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/22.png -------------------------------------------------------------------------------- /res/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/23.png -------------------------------------------------------------------------------- /res/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/3.png -------------------------------------------------------------------------------- /res/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/4.png -------------------------------------------------------------------------------- /res/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/5.png -------------------------------------------------------------------------------- /res/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/6.png -------------------------------------------------------------------------------- /res/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/7.png -------------------------------------------------------------------------------- /res/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/8.png -------------------------------------------------------------------------------- /res/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyingtime/go-https/a7df052761c6e9b9cc896b88221b330eca0a5945/res/9.png -------------------------------------------------------------------------------- /root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDJjCCAg4CCQDlCkTaHmqTdjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJD 3 | TjERMA8GA1UECAwIU2hhbmRvbmcxEDAOBgNVBAcMB1FpbmdkYW8xITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNTEyMDcwNzE1MTlaFw0yNTEy 5 | MDQwNzE1MTlaMFUxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZG9uZzEQMA4G 6 | A1UEBwwHUWluZ2RhbzEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk 7 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy/Lag3ykmeu6CLGe0Zbu 8 | gSwhkW2Ks/a3dJOiIi67PCRdJLTRQKlWmjdi2k9bN/PRSqQAqY0laFyw14zIutML 9 | 21QMcLqHcGJZjuAfoBsnGOtTGmmKbcswYsYv9lZkWib9Ql7lZ4IOScvqtAc2/Npu 10 | c/L1L7iV6x1gtkHkH6TX20r6c3ouBustX6mhtM3cKPo3rzxOqeoBkjM4NkB3e5gV 11 | A9tUIr0vwSuEoqXKmqRmuza3e46BXYovons1Q6Cs/Nk69tFH58EqtPsnskjsibIi 12 | QPNtzzsUJDsQwYmI1tIA+oOUlXdlyj0vUMgh1/S6FCtxIT8U5uK/pUrihaorMHta 13 | LwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAp4pTEUILTFQSnj7hjxR1M6wY591dx 14 | 4ZCn3EQoeKjQfKWUYc4zPisGUooF4DBMngGJMgu7jDx944mK4ZnmCBCzBjGCiVRq 15 | Pi3UkXcTSuhOZMhIpk29J1XBN1H8IDut2o0uKmpm3a3vMnfhz636AIjADXLRtevw 16 | ryrYr9AgDAzhyf0jxq6ou0le/EHC6i1uf/Y9ygm+beTzrfmplQRjM3Q8QlK0pHUf 17 | znp1HfFBKg8iZt8IfXBDHSF120SO8Q9QQ3f2++5d68bBYcFkadDA9eqjuQ2D4Qaa 18 | yGJ+xgLgO/aebQIWfOPT96Yn5KIhwAa2TQF2xvQb0j4s5TYTERmkcUoR 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /root.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICmjCCAYICAQAwVTELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoYW5kb25nMRAw 3 | DgYDVQQHDAdRaW5nZGFvMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBM 4 | dGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDL8tqDfKSZ67oIsZ7R 5 | lu6BLCGRbYqz9rd0k6IiLrs8JF0ktNFAqVaaN2LaT1s389FKpACpjSVoXLDXjMi6 6 | 0wvbVAxwuodwYlmO4B+gGycY61MaaYptyzBixi/2VmRaJv1CXuVngg5Jy+q0Bzb8 7 | 2m5z8vUvuJXrHWC2QeQfpNfbSvpzei4G6y1fqaG0zdwo+jevPE6p6gGSMzg2QHd7 8 | mBUD21QivS/BK4SipcqapGa7Nrd7joFdii+iezVDoKz82Tr20UfnwSq0+yeySOyJ 9 | siJA823POxQkOxDBiYjW0gD6g5SVd2XKPS9QyCHX9LoUK3EhPxTm4r+lSuKFqisw 10 | e1ovAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAW/cTYhNXuwQsC3KSzUKYkSKo 11 | tpOdb7+xdV28REalwgE79WkDYEvlZtodEXA26/6ISb7bZa6T8/RYHEUofSoEolOL 12 | wjgXoh1FTwzlUefHIk2VRQ8Ewwn7GQJsc+DTIRoMsJsF0emMT/1Ud2s5sUzyRAWV 13 | H+8X6m/XoT2keNwZT0WB0log2zo3kh71+5RveT7O9qeCC5OrJOt6xPSr1Y6NEFEr 14 | cLpIvMMYuHFWfvosaz/Ki85YZfleisTo0hy4xl0vTAOcx7uTDKqXh4DxCLjZp6hJ 15 | 07armaLtx9OW5V6yAMnV+zG6Rux5EEsmualSp0KEUaqmDO7FvPx9i7+4MrCC3g== 16 | -----END CERTIFICATE REQUEST----- 17 | -------------------------------------------------------------------------------- /root.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,9F12B114D56B0801 4 | 5 | et0sIF2gbtqm5iyzJZEywb3dU1Zbg4S0M0d0tr1o/MO/cDe3ZLptKqJR7gz+lxVJ 6 | 9C2MN0Yrkno6Spe+9JQr3xY9LFegDs+3lFC95oTOv3dFEjFZHKg+9rljd0SyntCB 7 | qjoQ8ihPbUFaHLLSLTGJbpaV/9XkIlATdG8zCfNG+Paab+EdXqJCvH17mQGhsmxj 8 | AgmAI1gWfFiZf1DIpxYXTfkSawaWi9Mwi2hrjTsVn4Yz5AFLgm/7/lnbDucYUW6F 9 | pFj3fRq+5ZtPK4EcIfvgsZRRdXkPIFp9qGXHOf3Xj0dc4IZZJg7d4QbfX2TWLWfe 10 | CHWrDfXbSLfvaEfSyHDPr5yD4uh576/MKgR4D14aSDzEsOsANyWNhqJLxu4X5gdY 11 | zn2NObixknlwa13LVIhD3MGOBOgw7xlmDlZGfJTOlIoIcVt8ZbPJWMRjx3M7P+I+ 12 | cLfGzk5E45WhgttaUFFa0o4hwwxqNwZzvFSDNlSgLERCeXWISqTUzjdx4HryHn8S 13 | ZE2b1y6NfCI34CJYBhALZMBqZm6r9MrfxT+/lGAvoD6jvT/MXNmJCzOCigj5+Yur 14 | DxsKjkPiafZ6TLtESNbykTXNGG45LCU2JokJhiz0r9uCoPPaSBr9zLXaGFjvidJ+ 15 | A97sz8q+SBt0IHIgVBLaP4P49vbPM2jSTGrk9CodM38XHt3LaCGn/wfXL6p/If5R 16 | c2U7BLTmPQaBz4cQGu3URSkUqEDB78OzQAq5U+oD0ZspJG8CzFLsSPfkOJzAzsU+ 17 | kZK4uHwhRO8KJi1E260uXPtDbCpF0woUPccpIL3ZeKpl9j5niDjuWvbDou9ThXV/ 18 | dsfB0tVT8fcNBEvoLOgWm03GmP7DlbhQZPbBR8/miB58XDv4tCoox259uSIhXOH6 19 | rQeaiNUryUxC5g+62q+JyAJ20UI0awZcwHbLvsFOF0vZZfHtcwoj0uloCRAKg+hy 20 | lGzmrcgBfpVH0Sidi9w/0iP+MrjGv/xZF/GIay/vhb3VZjgz5AECvUr8erzFEsJn 21 | ZNXx3ktnlfMVbhedOI+wS5yoJaq0qXIwfdTYz+pi0ljd/rLaw8tCVcoOVwy+Mmtp 22 | UNrkixbXsW1BmP2KHEZi7V2SJqT9eh6/sgbo9W6sH8GFpWxjR9pZpwIeQDWoYzo0 23 | jBHuwgsSDvYRaoBSbZU+BKHGgRcmFlVLDEVTmI7cATgPGuyu2J8KusiBivQZomXc 24 | KEnBl4lJFIoQ4YSEdZYv/pHhbpCFu8xNUJaqkonoCUlaLwXnm8EREzlNf5i1c0RF 25 | xvCGU7msuUrnBIxB/7xScUrt0IgKu4Iqan8RQY5ck/gFTVbmBneulD5X2BFwEC0N 26 | uZzEOCAUmAgevvrd2v97JikZ0Cd2yESsbTWX7K89BERo5wtR2lQ8DrQNkVn2KGWq 27 | AkdKn7sxc3NB1Dn3152doYCFm+tAHyCRYH7tuFqDGVAa9qo1pRjATWfjuPyxWSEr 28 | l/gRmAta86RPiJ6ImPnhPPvL9xqnGNDjcqPKpY3riywUAd9wwC4aSedAcPLubf8h 29 | 2cMzI0nwL0jT2juPiaElfCVPXLJsjcYEC5f8xjd2Vd0ZSFGW5sVIHcg0w+pHuOqw 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /root.srl: -------------------------------------------------------------------------------- 1 | ABC3E1B4D7F48937 2 | -------------------------------------------------------------------------------- /server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDVzCCAj8CCQCrw+G01/SJNjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJD 3 | TjERMA8GA1UECAwIU2hhbmRvbmcxEDAOBgNVBAcMB1FpbmdkYW8xITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNTEyMDcwNzMyMTNaFw0xNjEy 5 | MDYwNzMyMTNaMIGFMQswCQYDVQQGEwJDTjERMA8GA1UECAwIU2hhbmRvbmcxEDAO 6 | BgNVBAcMB1FpbmdkYW8xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 7 | ZDESMBAGA1UEAwwJbG9jYWxob3N0MRowGAYJKoZIhvcNAQkBFgt4eHhAeHh4LmNv 8 | bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMqSzzcyg7ePLt7KZZjk 9 | Vau5MVMJTCqJCLVirQw3eRLndFOO3K4o7L8qUD6AKo80WnEaKRgg0zUQtxRhq1a3 10 | d3QUELyGL88JdD/WJj2Xrj0cIdOHNeScuSxkO/ivrIf05j2DGcbGL/zcDXssnKlj 11 | 3zvYNIXvoYU6ye0NGBfjW9Iw2x5dSVK0AibCb40lLUy/ZRgjdl3+pSzdkIh2e65P 12 | aEew8TsmomCpFQdG0b48eFjhBXlF34UOotEzT3JGaY+HJd8P5ERloOhppEdC8zQv 13 | dEPtY4+MJhVPXPnDwY6+IzWK/qk05G6LS1jrjw88NK/KjGbRTlTS1TySYOB6I0UR 14 | AFMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAD7GTwVlQkczJH9nPMdKbhHH4zl2C 15 | LJXvPJAahiBMhkQUW+xPMCkSUoUbgo96EiLSJ58qK5i7L141LV1eeemdf1KfeBEF 16 | w6GPY1V2wv5G++MsWR95DCBb0urDyF20Om4O/oS3FJtia8ICJAFPbGntty0JUp06 17 | PRqDF1BqQ6ePRqrRLde+jgAwF8dUEI83QkSgECHAjWrPK8j1hv/nv72FXREN0SwX 18 | T3fZnra+t6K6XAPHYZ+gWbakEqNr3rfieNE8jJvTsrLmdcGD2uwZqMYZstpOtj4u 19 | 7CU6T4LG1IWNKnRYfMIfpiey8zmYoLrQTwCMX+QOFbd6RcrwiyXnH0paUg== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICyzCCAbMCAQAwgYUxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZG9uZzEQ 3 | MA4GA1UEBwwHUWluZ2RhbzEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg 4 | THRkMRIwEAYDVQQDDAlsb2NhbGhvc3QxGjAYBgkqhkiG9w0BCQEWC3h4eEB4eHgu 5 | Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAypLPNzKDt48u3spl 6 | mORVq7kxUwlMKokItWKtDDd5Eud0U47crijsvypQPoAqjzRacRopGCDTNRC3FGGr 7 | Vrd3dBQQvIYvzwl0P9YmPZeuPRwh04c15Jy5LGQ7+K+sh/TmPYMZxsYv/NwNeyyc 8 | qWPfO9g0he+hhTrJ7Q0YF+Nb0jDbHl1JUrQCJsJvjSUtTL9lGCN2Xf6lLN2QiHZ7 9 | rk9oR7DxOyaiYKkVB0bRvjx4WOEFeUXfhQ6i0TNPckZpj4cl3w/kRGWg6GmkR0Lz 10 | NC90Q+1jj4wmFU9c+cPBjr4jNYr+qTTkbotLWOuPDzw0r8qMZtFOVNLVPJJg4Hoj 11 | RREAUwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAEBdkwmnIlkGRev/9m+RN0sc 12 | AII70yOWc79cv5sBCdGGOKfa6f3p8d0zPiy4jnKejqhgAQ0nI2MNMPllEDR9ysAt 13 | Bzzffgdirk2QWc8sJEp3rXAXfp9ggfuKO1s4+etWdsF7oJKqC3IxRwh1FIfOdwlh 14 | EEpHDSmMSUJctyTSxgKbXtlU85qPVLoLW5DrKkTalHsZIx41rcC8RJE55QP7XBOq 15 | w3o3hU6oohT4mApA461OjnRG3y5YBRzaJcFntxbYIfaugsQBLZ5GW3TAIPJ88eHe 16 | Xy7UwlTN84OAB8esxd1e0xUFSg+Jx6qWUMj6D7BE0d9NntAQhbpdIPNqoDwvXJQ= 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | ) 11 | 12 | type httpsHandler struct { 13 | } 14 | 15 | func (*httpsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 16 | io.WriteString(w, "golang https server!!!") 17 | } 18 | 19 | func main() { 20 | pool := x509.NewCertPool() 21 | caCertPath := "root.crt" 22 | 23 | caCrt, err := ioutil.ReadFile(caCertPath) 24 | if err != nil { 25 | log.Fatal("ReadFile err:", err) 26 | return 27 | } 28 | pool.AppendCertsFromPEM(caCrt) 29 | 30 | s := &http.Server{ 31 | Addr: ":8080", 32 | Handler: &httpsHandler{}, 33 | TLSConfig: &tls.Config{ 34 | ClientCAs: pool, 35 | ClientAuth: tls.RequireAndVerifyClientCert, 36 | }, 37 | } 38 | 39 | if err = s.ListenAndServeTLS("server.crt", "server.key"); err != nil { 40 | log.Fatal("ListenAndServeTLS err:", err) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEAypLPNzKDt48u3splmORVq7kxUwlMKokItWKtDDd5Eud0U47c 3 | rijsvypQPoAqjzRacRopGCDTNRC3FGGrVrd3dBQQvIYvzwl0P9YmPZeuPRwh04c1 4 | 5Jy5LGQ7+K+sh/TmPYMZxsYv/NwNeyycqWPfO9g0he+hhTrJ7Q0YF+Nb0jDbHl1J 5 | UrQCJsJvjSUtTL9lGCN2Xf6lLN2QiHZ7rk9oR7DxOyaiYKkVB0bRvjx4WOEFeUXf 6 | hQ6i0TNPckZpj4cl3w/kRGWg6GmkR0LzNC90Q+1jj4wmFU9c+cPBjr4jNYr+qTTk 7 | botLWOuPDzw0r8qMZtFOVNLVPJJg4HojRREAUwIDAQABAoIBABhTdOrN+B9M5HYA 8 | nB62HMuYW6H7FdhtyEvv45P5/WIVxVRbbYjEhVmXfTdkMLgts0atu42YM4TF0xZx 9 | fB/XvFKGLlRVUNxt6DXaQ5FV66iO/kjmjcQ8Rchc6Q6+GdvhvtxYJ/pExnJ5Am1u 10 | OAnnYmFPX09OLXlQS/tZfTExLk+ZM4rHyn3SU3OD/JAq9Z8C0WdhmaJLjwf7r7qJ 11 | NEibte0fXyAkQ9t8kC8hEtyX3wmW7OsCVu9ODJwanYS83k5gxuqqbTyf5MKBMBKX 12 | ZXUXB8MU6jEYQOudeGHPCKwKF2JeD/Xrs5aLiDtT5DFVKg23sQoerRdCLPRatJh7 13 | 20DfMwECgYEA8jevu+aMclKrA8/mvLBN6tEVyGdoLTtFOdiHO7BW8oUBSWha9nfA 14 | y4r8RdqQsSbTznyous/zcsRw2PWYPRhvkn8+e59dcwRQqW76sfCUtD3VLzdJh24M 15 | NZ4n9JzL8TWoB0QeEf9YZ7DFE+IlgPyxzl7MVWHg7R/NpeS4iWNSGJMCgYEA1hmj 16 | r/r+Vtfyud4tqXjXu+nsiExsqJ8USCwZL2iZdYnIscsCMIEgoyTxjGuuhcP54FUu 17 | SavmsHe9I/NVAusNxmWxy01c+AK9wDxK2wsedpITWUwD1s1O3TdTYFRq9c6GtGL0 18 | CEsvi806mXP09Q2qHtew8brTEApNpRXlADFtEUECgYBvPhoMrzbjronyZ0JueH5g 19 | kQRzFOLomycRCRwa0sMsAN/1aeMU/SzjjoKMRnRbmByA4gnQOn9xvzyguDLiJF3h 20 | p2T3+9o8X8f3+QtUO8zf9uH5HGg9tdIPsgJhur2Dm4P/Sk6RL3fXr3zjw+I7mlLD 21 | GBC6Sgi2fvvA7AnAt4fV1wKBgD6wESp0zkW1Qx/C+xG1DU27J4OdBO+2bGTZbKJh 22 | +RTePAI607BKDrlWFterq9UE1cQmjMALcidXV+0P0WNiWY0ut4k0ZLVFcDO6M5zB 23 | O7EyAjJSPImHYcEJ8wKwlQTV7MEifBt1kD1Z4P+PYTjjQF15gBi3QBdhPOzKZVvS 24 | HQJBAoGAOo9rIaOXKotEYM8SK29QRRCdsjcggpEL7dVBrc6+KBnBTd25DcexMDRa 25 | Rf9MwkSFI9+izAJZApeZS7fOkpt067bd+9nt35tXGI4bYO5sXXaPqRWgYw2Vhp8u 26 | M4c1TRO0GSG6NXtey8TtgAZHjHQ8ZuYTKJzNIQXa5b4lJyhrRHM= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /server_single.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | func handler(w http.ResponseWriter, r *http.Request) { 10 | io.WriteString(w, "golang https server") 11 | } 12 | 13 | func main() { 14 | http.HandleFunc("/", handler) 15 | if err := http.ListenAndServeTLS(":8080", "server.crt", "server.key", nil); err != nil { 16 | log.Fatal("ListenAndServe:", err) 17 | } 18 | } 19 | --------------------------------------------------------------------------------