-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
支持TLS传输国密 #290
base: master
Are you sure you want to change the base?
支持TLS传输国密 #290
Conversation
kernel/network/p2p/util.go
Outdated
@@ -20,32 +26,79 @@ import ( | |||
"github.com/xuperchain/xupercore/kernel/network/config" | |||
) | |||
|
|||
// serverName 为key,缓存 creds | |||
var serverNameMap = make(map[string]credentials.TransportCredentials) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
全局变量的读写最好加锁进行保护
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
好的
kernel/network/p2p/util.go
Outdated
} | ||
|
||
//如果缓存中有值 | ||
if creds, ok := serverNameMap[serviceName]; ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serverNameMap 对应性能等没有实质性的作用,反而增加了代码的复杂度。
TransportCredentials 的使用包括两种场景
- 服务端: Accept 完成 TCP 三次握手之后,调用 Server 对象上的 opts.creds 完成SSL 握手中的服务端部分,不会重复加载TransportCredentials
- 客户端: 底层采用 HTTP2 长链接,同一个服务端只有一个连接,不需要重复加载TransportCredentials,serverNameMap 缓存 基本处于缓存不命中的情况,对性能等没有实质性的帮助
kernel/network/p2p/util.go
Outdated
func NewTLS(path, serviceName string) (credentials.TransportCredentials, error) { | ||
|
||
if len(serviceName) < 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
去掉 ServerName 为空的判断,标准库TLS 是允许ServerName 为空的
ServerName 为空时,标准库中 SSL 握手的证书为
- 客户端: 根据连接时根据 dial 的 addr 判断自动推断 ServerName
- 服务端: 不需要 ServerName 字段
gmtls 的逻辑应该也类似,可以进一步确认
kernel/network/p2p/util.go
Outdated
if !ok { | ||
return nil, err | ||
} | ||
certificate, err := tls.LoadX509KeyPair(filepath.Join(path, "cert.pem"), filepath.Join(path, "private.key")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gmtls 中的 x509 证书兼容标准的 RSA x509 解析,同一个证书只需要加载和解析一次,可以参考官方示例
https://github.com/tjfoc/gmsm/blob/fdaa5ff368db5ce62bb672fc424b23f8923858dc/gmtls/websvr/websvr.go#L52
kernel/network/p2p/util.go
Outdated
ClientAuth: tls.RequireAndVerifyClientCert, | ||
}) | ||
return creds, nil | ||
if strings.Contains(strings.ToLower(x509cert.SignatureAlgorithm.String()), "sm") { //国密 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修改判断是否使用国密的逻辑,区分客户端和服务端
客户端通过配置项选择是否使用国密,或者通过本地证书判断支持的密码学套件
服务端支持支持加载多个证书,根据 SSL 握手时协商的结果选择对应的密码学套件
理由如下
其中,ClientHello 结构中包含了客户端支持的加密套件,服务端根据自身的支持的加密套件和客户端支持的加密套件返回对应的加密套件协商结果。
客户端是否使用国密可以通过以下方案判断
- 通过配置项来判断是否使用国密
- 通过判断证书类型确定是否使用国密。
值得注意的是,在商用密码系列算法中,SM2为公钥加密, SM3 为哈希算法,SM4 为分组加密。gmtls 支持SM2,SM3,SM4 其中只有SM2 可能出现在证书的 PublicKeyAlgorithm 字段,而不必要使字符串比较。
服务端通过如下方案
服务端在收到 Client 服务端在 ClientHello 信息之后,会通过 ClientHelloHello 信息之后,会通过 ClientHello 中的 SupportedVersions 字段决定是否使用国密。
kernel/network/p2p/util.go
Outdated
certPool := x509.NewCertPool() | ||
ok := certPool.AppendCertsFromPEM(bs) | ||
if !ok { | ||
cacert, err := ioutil.ReadFile(filepath.Join(path, "cacert.pem")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bs 和 cacert 是同样的内容,不需要重复读取
Codecov Report
@@ Coverage Diff @@
## master #290 +/- ##
==========================================
- Coverage 45.81% 45.65% -0.16%
==========================================
Files 138 138
Lines 12284 12307 +23
==========================================
- Hits 5628 5619 -9
- Misses 5504 5534 +30
- Partials 1152 1154 +2
Continue to review full report at Codecov.
|
kernel/network/p2p/util.go
Outdated
return nil, err | ||
} | ||
|
||
certificate, err := defaulttls.LoadX509KeyPair(filepath.Join(path, "cert.pem"), filepath.Join(path, "private.key")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
通 70 行 comment
Description
What is the purpose of the change?
基于 github.com/tjfoc/gmsm 实现TLS传输加密,使用双证书模式,实际是一个证书对象,slice里放了两次,简化操作
Fixes # (issue)
Type of change
Please delete options that are not relevant.
Brief of your solution
基于 github.com/tjfoc/gmsm 实现TLS传输加密,使用双证书模式,实际是一个证书对象,slice里放了两次,简化操作