github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/gmtls/tls_test/tls_test.go (about) 1 // Copyright (c) 2022 zhaochun 2 // gmgo is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 package tls_test 10 11 import ( 12 "fmt" 13 "io/ioutil" 14 "net" 15 "net/http" 16 "testing" 17 "time" 18 19 "gitee.com/zhaochuninhefei/zcgolog/zclog" 20 "github.com/hxx258456/ccgo/gmtls" 21 "github.com/hxx258456/ccgo/x509" 22 ) 23 24 //goland:noinspection GoUnusedConst 25 const ( 26 SM2CaCertPath = "./certs/sm2_ca_cert.cer" 27 SM2AuthCertPath = "./certs/sm2_auth_cert.cer" 28 SM2AuthKeyPath = "./certs/sm2_auth_key.pem" 29 sm2SignCertPath = "./certs/sm2_sign_cert.cer" 30 sm2SignKeyPath = "./certs/sm2_sign_key.pem" 31 sm2UserCertPath = "certs/sm2_auth_cert.cer" 32 sm2UserKeyPath = "certs/sm2_auth_key.pem" 33 ) 34 35 var end chan bool 36 37 func Test_tls13(t *testing.T) { 38 end = make(chan bool, 64) 39 go ServerRun(true) 40 time.Sleep(5 * time.Second) 41 go ClientRunTls13() 42 <-end 43 fmt.Println("Test_tls13 over.") 44 } 45 46 func Test_gmssl(t *testing.T) { 47 end = make(chan bool, 64) 48 go ServerRun(true) 49 time.Sleep(5 * time.Second) 50 go ClientRunGMSSL() 51 <-end 52 fmt.Println("Test_gmssl over.") 53 } 54 55 // 启动服务端 56 func ServerRun(needClientAuth bool) { 57 err := zclog.ClearDir("logs") 58 if err != nil { 59 panic(err) 60 } 61 zcgologConfig := &zclog.Config{ 62 LogFileDir: "logs", 63 LogFileNamePrefix: "tlstest", 64 LogMod: zclog.LOG_MODE_SERVER, 65 LogLevelGlobal: zclog.LOG_LEVEL_DEBUG, 66 } 67 zclog.InitLogger(zcgologConfig) 68 // 导入tls配置 69 config, err := loadServerConfig(needClientAuth) 70 if err != nil { 71 panic(err) 72 } 73 // 定义tls监听器 74 ln, err := gmtls.Listen("tcp", ":50052", config) 75 if err != nil { 76 zclog.Println(err) 77 return 78 } 79 defer func(ln net.Listener) { 80 err := ln.Close() 81 if err != nil { 82 panic(err) 83 } 84 }(ln) 85 86 // 定义http请求处理 87 http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) { 88 clientName := request.URL.Query().Get("clientName") 89 fmt.Printf("接受到来自 %s 的http请求...\n", clientName) 90 // 在http响应中写入内容 91 _, err := fmt.Fprintf(writer, "你好, %s ! \n", clientName) 92 if err != nil { 93 panic(err) 94 } 95 }) 96 // fmt.Println("============ HTTP服务(基于GMSSL或TLS) 已启动 ============") 97 98 // 在tls监听器上开启https服务 99 err = http.Serve(ln, nil) 100 if err != nil { 101 panic(err) 102 } 103 } 104 105 func ClientRunGMSSL() { 106 // 创建客户端本地的证书池 107 certPool := x509.NewCertPool() 108 // 读取sm2 ca证书 109 cacert, err := ioutil.ReadFile(SM2CaCertPath) 110 if err != nil { 111 zclog.Fatal(err) 112 } 113 // 将sm2ca证书作为根证书加入证书池 114 // 即,客户端相信持有该ca颁发的证书的服务端 115 certPool.AppendCertsFromPEM(cacert) 116 117 // 读取sm2User证书与私钥,作为客户端的证书与私钥,一般用作密钥交换证书。 118 // 但如果服务端要求查看客户端证书(双向tls通信)则也作为客户端身份验证用证书, 119 // 此时该证书应该由第三方ca机构颁发签名。 120 cert, _ := gmtls.LoadX509KeyPair(sm2UserCertPath, sm2UserKeyPath) 121 122 // 定义gmtls配置 123 // 选择最高tls协议版本为VersionGMSSL, 服务端选择的默认密码套件将是 TLS_SM4_GCM_SM3 124 config := &gmtls.Config{ 125 RootCAs: certPool, 126 Certificates: []gmtls.Certificate{cert}, 127 // 因为sm2相关证书是由`x509/x509_test.go`的`TestCreateCertFromCA`生成的, 128 // 指定了SAN包含"server.test.com" 129 ServerName: "server.test.com", 130 MaxVersion: gmtls.VersionGMSSL, 131 } 132 133 // 向服务端拨号,建立tls连接 134 conn, err := gmtls.Dial("tcp", "localhost:50052", config) 135 if err != nil { 136 panic(err) 137 } 138 defer func(conn *gmtls.Conn) { 139 err := conn.Close() 140 if err != nil { 141 panic(err) 142 } 143 }(conn) 144 145 // fmt.Println("============ gmtls客户端(gmssl)连接服务端,握手成功 ============") 146 // time.Sleep(time.Minute) 147 // 定义http请求 148 req := []byte("GET /test?clientName=gmtlsClient(gmssl) HTTP/1.1\r\n" + 149 "Host: localhost\r\n" + 150 "Connection: close\r\n\r\n") 151 // 向tls连接写入请求 152 _, _ = conn.Write(req) 153 154 // fmt.Println("============ gmtls客户端(gmssl)向服务端发送http请求 ============") 155 156 // 从tls连接中读取http请求响应 157 buff := make([]byte, 1024) 158 for { 159 n, _ := conn.Read(buff) 160 if n <= 0 { 161 break 162 } else { 163 fmt.Printf("%s", buff[0:n]) 164 } 165 } 166 // fmt.Println("============ gmtls客户端(gmssl)与服务端连接测试成功 ============") 167 end <- true 168 } 169 170 func ClientRunTls13() { 171 // 创建客户端本地的证书池 172 certPool := x509.NewCertPool() 173 // 读取sm2 ca证书 174 cacert, err := ioutil.ReadFile(SM2CaCertPath) 175 if err != nil { 176 zclog.Fatal(err) 177 } 178 // 将sm2ca证书作为根证书加入证书池 179 // 即,客户端相信持有该ca颁发的证书的服务端 180 certPool.AppendCertsFromPEM(cacert) 181 182 // 读取sm2User证书与私钥,作为客户端的证书与私钥,一般用作密钥交换证书。 183 // 但如果服务端要求查看客户端证书(双向tls通信)则也作为客户端身份验证用证书, 184 // 此时该证书应该由第三方ca机构颁发签名。 185 cert, _ := gmtls.LoadX509KeyPair(sm2UserCertPath, sm2UserKeyPath) 186 187 // 定义gmtls配置 188 // 默认最高tls协议版本为tls1.3, 服务端选择的默认密码套件将是 TLS_SM4_GCM_SM3 189 config := &gmtls.Config{ 190 RootCAs: certPool, 191 Certificates: []gmtls.Certificate{cert}, 192 // 因为sm2相关证书是由`x509/x509_test.go`的`TestCreateCertFromCA`生成的, 193 // 指定了SAN包含"server.test.com" 194 ServerName: "server.test.com", 195 } 196 // 要启用psk,除了默认SessionTicketsDisabled为false,还需要配置客户端会话缓存为非nil。 197 // 这样服务端才会在握手完成后发出 newSessionTicketMsgTLS13 将加密并认证的会话票据发送给客户端。 198 config.ClientSessionCache = gmtls.NewLRUClientSessionCache(1) 199 200 // 向服务端拨号,建立tls连接 201 conn, err := gmtls.Dial("tcp", "localhost:50052", config) 202 if err != nil { 203 panic(err) 204 } 205 defer func(conn *gmtls.Conn) { 206 err := conn.Close() 207 if err != nil { 208 panic(err) 209 } 210 }(conn) 211 212 // fmt.Println("============ gmtls客户端(tls1.3)连接服务端,握手成功 ============") 213 // time.Sleep(time.Minute) 214 // 定义http请求 215 req := []byte("GET /test?clientName=gmtlsClient(tls1.3) HTTP/1.1\r\n" + 216 "Host: localhost\r\n" + 217 "Connection: close\r\n\r\n") 218 // 向tls连接写入请求 219 _, _ = conn.Write(req) 220 221 // fmt.Println("============ gmtls客户端(tls1.3)向服务端发送http请求 ============") 222 223 // 从tls连接中读取http请求响应 224 buff := make([]byte, 1024) 225 for { 226 n, _ := conn.Read(buff) 227 if n <= 0 { 228 break 229 } else { 230 fmt.Printf("%s", buff[0:n]) 231 } 232 } 233 // fmt.Println("============ gmtls客户端(tls1.3)与服务端连接测试成功 ============") 234 end <- true 235 } 236 237 func loadServerConfig(needClientAuth bool) (*gmtls.Config, error) { 238 // 读取sm2Sign证书与私钥,作为国密tls场景的服务器证书用 239 sigCert, err := gmtls.LoadX509KeyPair(sm2SignCertPath, sm2SignKeyPath) 240 if err != nil { 241 return nil, err 242 } 243 // 返回服务端配置 244 config, err := gmtls.NewServerConfigByClientHello(&sigCert, &sigCert) 245 if err != nil { 246 return nil, err 247 } 248 249 if needClientAuth { 250 // 如果服务端想要验证客户端身份,在这里添加对应配置信任的根证书 251 certPool := x509.NewCertPool() 252 cacert, err := ioutil.ReadFile(SM2CaCertPath) 253 if err != nil { 254 return nil, err 255 } 256 certPool.AppendCertsFromPEM(cacert) 257 config.ClientAuth = gmtls.RequireAndVerifyClientCert 258 config.ClientCAs = certPool 259 // config.SessionTicketsDisabled = false 260 fmt.Println("------ debug用 : 服务端配置了ClientAuth") 261 } 262 263 return config, nil 264 } 265 266 func Test_clearLogs(t *testing.T) { 267 err := zclog.ClearDir("logs") 268 if err != nil { 269 panic(err) 270 } 271 }