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  }