...

Text file src/github.com/tjfoc/gmsm/gmtls/websvr/README.md

Documentation: github.com/tjfoc/gmsm/gmtls/websvr

     1# TLS/GMSSL 服务端协议自适应
     2
     3目录结构说明:
     4
     5```
     6├─certs        // 证书以及密钥
     7├─websvr_test   //HTTP服务端/客户端测试Demo
     8└─websvr          //协议自适应实现
     9```
    10
    11## 服务端 GMTLS/TLS 工作逻辑
    12
    13![autoswitchlogic](./img/autoswitchlogic.png)
    14
    15
    16通过配置`gmtls.Config` 对象提供自动切换相关的配置,创建`gmtls.Conn`。
    17
    18在对`gmtls.Conn`的`Read/Wirte`时将会触发握手行为`HandShake`。
    19
    20`HandShake`会根据用户配置参数,判断需要使用 GMSSL、TLS、GMSSL/TLS 三种工作模式中的哪一种,
    21然后进入到相应的工作模式中运行。
    22
    23- **TLS工作模式**:
    24    - 运行`serverHandshake` 进入TLS握手。
    25    - 创建TLS握手上下文`serverHandshakeState`。
    26    - 读取并处理 来自于客户端的ClientHello 消息。
    27    - 进入 TLS握手流程。
    28- **GMSSL工作模式**:
    29    - 运行`serverHandshakeGM` 进入GMSSL握手。
    30    - 创建TLS握手上下文`serverHandshakeStateGM`。
    31    - 读取并处理 来自于客户端的ClientHello 消息。
    32    - 进入 GMSSL握手流程。
    33- **GMSSL/TLS工作模式**:
    34    - 运行`serverHandshakeAutoSwitch` 进入自动切换的握手模式。
    35    - 读取来自于客户端的ClientHello 消息。
    36    - 分析处理ClientHello,根据客户端协议版本。
    37    - 根据协议版本,选择使用具体握手方式:
    38      - GMSSL: 创建上下文`serverHandshakeStateGM`,进入GMSSL握手流程。
    39      - TLS: 创建上下文`serverHandshakeState`,进入TLS握手流程。
    40
    41
    42在GMSSL/TLS模式的服务端运行过程中,如何根据客户端版本选择需要使用的证书以及密钥?
    43
    44自动切换模式,同时需要为服务端提供2份证书与密钥对(一份用于标准的TLS、一份用于GMSSL),
    45在运行过程需要使用到`gmtls.Config#GetCertificate`方法来根据客户端的版本选择出合适的
    46证书密钥对,即在客户端版本是GMSSL的时候返回SM2签名证书密钥对;在客户端版本是标准的TLS时
    47返还RSA/ECC的证书密钥对,以次来动态适应不同客户端的连接需求。
    48针对于GMSSL特殊的双证书需求,特别为`gmtls.Config`增加了一个方法`gmtls.Config#GetKECertificate`
    49通过该方法来提供GMSSL密钥交换过程中使用密钥对。
    50
    51更多细节实现见: [auto_handshake_server](../auto_handshake_server.go)
    52
    53## GMSSL/TLS 自动切换模式
    54
    55快速开始:
    56
    571. 准备 RSA、SM2签名、SM2加密,证书以及密钥对。
    582. 调用`gmtls.NewBasicAutoSwitchConfig`构造基础的配置对象。
    593. Use it.
    60
    61```go
    62func main() {
    63	config, err := gmtls.NewBasicAutoSwitchConfig(&sigCert, &encCert, &rsaKeypair)
    64	if err != nil {
    65		panic(err)
    66	}
    67
    68	ln, err := gmtls.Listen("tcp", ":443", config)
    69	if err != nil {
    70		panic(err)
    71	}
    72	defer ln.Close()
    73
    74	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    75		fmt.Fprintf(writer, "hello\n")
    76	})
    77	err = http.Serve(ln, nil)
    78	if err != nil {
    79		panic(err)
    80	}
    81}	
    82```
    83
    84
    85详细服务端的配置流程如下:
    86
    871. 准备:
    88   - SM2签名密钥对、证书:`sigCert`
    89   - SM2加密密钥对、证书:`encCert`
    90   - RSA/ECC加密密钥对、证书:`rsaKeypair`
    912. 创建一个实现`gmtls.Config#GetCertificate`方法签名的方法,方法需要根据支持的签名类型:
    92    - 含有GMSSL版本:返回SM2签名证书密钥对(`sigCert`)。
    93    - 不含有GMSSL版本:返回RSA签名证书密钥对(`rsaKeypair`)。
    943. 创建一个实现`gmtls.Config#GetKECertificate`方法签名的方法,固定返回SM2加密证书密钥对(`encCert`)。
    954. 创建`GMSupport`并启用,自动切换模式。
    965. 创建`gmtls.Config`对象,接下就可以启动服务端实现自动切换功能。
    97
    98```go
    99// Step 1:
   100fncGetSignCertKeypair := func(info *gmtls.ClientHelloInfo) (*gmtls.Certificate, error) {
   101    gmFlag := false
   102    // 检查支持协议中是否包含GMSSL
   103    for _, v := range info.SupportedVersions {
   104        if v == gmtls.VersionGMSSL {
   105        gmFlag = true
   106        break
   107        }
   108    }
   109    if gmFlag {
   110        return &sigCert, nil
   111    } else {
   112        return &rsaKeypair, nil
   113    }
   114}
   115
   116fncGetEncCertKeypair := func(info *gmtls.ClientHelloInfo) (*gmtls.Certificate, error) {
   117    return &encCert, nil
   118}
   119support := gmtls.NewGMSupport()
   120support.EnableMixMode()
   121config := &gmtls.Config{
   122    GMSupport:        support,
   123    GetCertificate:   fncGetSignCertKeypair,
   124    GetKECertificate: fncGetEncCertKeypair,
   125}
   126```
   127
   128> 更多细节请参考: [HTTP over GMTLS/TLS Server Demo](./websvr.go)
   129
   130
   131## 双向身份认证
   132
   133服务端开启双向身份认证,需要配置而外参数`ClientAuth`。
   134
   135建议使用`gmtls.RequireAndVerifyClientCert`表明服务端需要客户端证书请求且需要验证客户端证书。
   136
   137```go
   138config, err := gmtls.NewBasicAutoSwitchConfig(&sigCert, &encCert, &rsaKeypair)
   139if err != nil {
   140	panic(err)
   141}
   142
   143// 开启客户端的身份认证
   144config.ClientAuth = gmtls.RequireAndVerifyClientCert
   145```
   146
   147> 更多细节请参考:
   148> 
   149> - [自适应Web服务端 Demo websvr.go #loadAutoSwitchConfigClientAuth](./websvr.go)
   150
   151
   152
   153客户端的启用双向身份认证也需要配置,只需要提供认证所使用的证书密钥对就可以。
   154
   155例如:
   156
   157```go
   158config ,err = &gmtls.Config{
   159		GMSupport:          &gmtls.GMSupport{},
   160		RootCAs:            certPool,
   161		Certificates:       []gmtls.Certificate{authKeypair},
   162		InsecureSkipVerify: false,
   163}
   164```
   165
   166> 更多细节请参考:
   167>
   168> - [国际算法标准 客户端 Demo websvr.go #bothAuthConfig](./websvr.go)

View as plain text