# README
TLS/GMSSL 服务端协议自适应
目录结构说明:
├─certs // 证书以及密钥
├─websvr_test //HTTP服务端/客户端测试Demo
└─websvr //协议自适应实现
服务端 GMTLS/TLS 工作逻辑
通过配置gmtls.Config
对象提供自动切换相关的配置,创建gmtls.Conn
。
在对gmtls.Conn
的Read/Wirte
时将会触发握手行为HandShake
。
HandShake
会根据用户配置参数,判断需要使用 GMSSL、TLS、GMSSL/TLS 三种工作模式中的哪一种,
然后进入到相应的工作模式中运行。
- TLS工作模式:
- 运行
serverHandshake
进入TLS握手。 - 创建TLS握手上下文
serverHandshakeState
。 - 读取并处理 来自于客户端的ClientHello 消息。
- 进入 TLS握手流程。
- 运行
- GMSSL工作模式:
- 运行
serverHandshakeGM
进入GMSSL握手。 - 创建TLS握手上下文
serverHandshakeStateGM
。 - 读取并处理 来自于客户端的ClientHello 消息。
- 进入 GMSSL握手流程。
- 运行
- GMSSL/TLS工作模式:
- 运行
serverHandshakeAutoSwitch
进入自动切换的握手模式。 - 读取来自于客户端的ClientHello 消息。
- 分析处理ClientHello,根据客户端协议版本。
- 根据协议版本,选择使用具体握手方式:
- GMSSL: 创建上下文
serverHandshakeStateGM
,进入GMSSL握手流程。 - TLS: 创建上下文
serverHandshakeState
,进入TLS握手流程。
- GMSSL: 创建上下文
- 运行
在GMSSL/TLS模式的服务端运行过程中,如何根据客户端版本选择需要使用的证书以及密钥?
自动切换模式,同时需要为服务端提供2份证书与密钥对(一份用于标准的TLS、一份用于GMSSL),
在运行过程需要使用到gmtls.Config#GetCertificate
方法来根据客户端的版本选择出合适的
证书密钥对,即在客户端版本是GMSSL的时候返回SM2签名证书密钥对;在客户端版本是标准的TLS时
返还RSA/ECC的证书密钥对,以次来动态适应不同客户端的连接需求。
针对于GMSSL特殊的双证书需求,特别为gmtls.Config
增加了一个方法gmtls.Config#GetKECertificate
通过该方法来提供GMSSL密钥交换过程中使用密钥对。
更多细节实现见: auto_handshake_server
GMSSL/TLS 自动切换模式
快速开始:
- 准备 RSA、SM2签名、SM2加密,证书以及密钥对。
- 调用
gmtls.NewBasicAutoSwitchConfig
构造基础的配置对象。 - Use it.
func main() {
config, err := gmtls.NewBasicAutoSwitchConfig(&sigCert, &encCert, &rsaKeypair)
if err != nil {
panic(err)
}
ln, err := gmtls.Listen("tcp", ":443", config)
if err != nil {
panic(err)
}
defer ln.Close()
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
fmt.Fprintf(writer, "hello\n")
})
err = http.Serve(ln, nil)
if err != nil {
panic(err)
}
}
详细服务端的配置流程如下:
- 准备:
- SM2签名密钥对、证书:
sigCert
- SM2加密密钥对、证书:
encCert
- RSA/ECC加密密钥对、证书:
rsaKeypair
- SM2签名密钥对、证书:
- 创建一个实现
gmtls.Config#GetCertificate
方法签名的方法,方法需要根据支持的签名类型:- 含有GMSSL版本:返回SM2签名证书密钥对(
sigCert
)。 - 不含有GMSSL版本:返回RSA签名证书密钥对(
rsaKeypair
)。
- 含有GMSSL版本:返回SM2签名证书密钥对(
- 创建一个实现
gmtls.Config#GetKECertificate
方法签名的方法,固定返回SM2加密证书密钥对(encCert
)。 - 创建
GMSupport
并启用,自动切换模式。 - 创建
gmtls.Config
对象,接下就可以启动服务端实现自动切换功能。
// Step 1:
fncGetSignCertKeypair := func(info *gmtls.ClientHelloInfo) (*gmtls.Certificate, error) {
gmFlag := false
// 检查支持协议中是否包含GMSSL
for _, v := range info.SupportedVersions {
if v == gmtls.VersionGMSSL {
gmFlag = true
break
}
}
if gmFlag {
return &sigCert, nil
} else {
return &rsaKeypair, nil
}
}
fncGetEncCertKeypair := func(info *gmtls.ClientHelloInfo) (*gmtls.Certificate, error) {
return &encCert, nil
}
support := gmtls.NewGMSupport()
support.EnableMixMode()
config := &gmtls.Config{
GMSupport: support,
GetCertificate: fncGetSignCertKeypair,
GetKECertificate: fncGetEncCertKeypair,
}
更多细节请参考: HTTP over GMTLS/TLS Server Demo
双向身份认证
服务端开启双向身份认证,需要配置而外参数ClientAuth
。
建议使用gmtls.RequireAndVerifyClientCert
表明服务端需要客户端证书请求且需要验证客户端证书。
config, err := gmtls.NewBasicAutoSwitchConfig(&sigCert, &encCert, &rsaKeypair)
if err != nil {
panic(err)
}
// 开启客户端的身份认证
config.ClientAuth = gmtls.RequireAndVerifyClientCert
更多细节请参考:
客户端的启用双向身份认证也需要配置,只需要提供认证所使用的证书密钥对就可以。
例如:
config ,err = &gmtls.Config{
GMSupport: &gmtls.GMSupport{},
RootCAs: certPool,
Certificates: []gmtls.Certificate{authKeypair},
InsecureSkipVerify: false,
}
更多细节请参考:
# Constants
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author