-
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
Changes from 9 commits
b9b76f6
ac1d616
da89cbe
a1550e8
d803c08
06fad94
e69054b
19aad14
f62c59a
6eb724e
7e4c02c
1713c7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,16 +2,23 @@ package p2p | |
|
||
import ( | ||
"crypto/rand" | ||
"crypto/tls" | ||
"crypto/x509" | ||
defaulttls "crypto/tls" | ||
defaultx509 "crypto/x509" | ||
"encoding/base64" | ||
"encoding/pem" | ||
"errors" | ||
"io/ioutil" | ||
math_rand "math/rand" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"sync" | ||
"time" | ||
|
||
tls "github.com/tjfoc/gmsm/gmtls" | ||
"github.com/tjfoc/gmsm/gmtls/gmcredentials" | ||
"github.com/tjfoc/gmsm/x509" | ||
|
||
iaddr "github.com/ipfs/go-ipfs-addr" | ||
"github.com/libp2p/go-libp2p-core/crypto" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
|
@@ -20,32 +27,85 @@ import ( | |
"github.com/xuperchain/xupercore/kernel/network/config" | ||
) | ||
|
||
// serverName 为key,缓存 creds | ||
var serverNameMap = make(map[string]credentials.TransportCredentials) | ||
|
||
//修改全局变量 serverNameMap 加锁 | ||
var mu sync.Mutex | ||
|
||
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 commentThe reason will be displayed to describe this comment to others. Learn more. 去掉 ServerName 为空的判断,标准库TLS 是允许ServerName 为空的
|
||
return nil, errors.New("serviceName is empty") | ||
} | ||
|
||
//如果缓存中有值 | ||
if creds, ok := serverNameMap[serviceName]; ok { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. serverNameMap 对应性能等没有实质性的作用,反而增加了代码的复杂度。
|
||
return creds, nil | ||
} | ||
|
||
mu.Lock() | ||
defer mu.Unlock() | ||
//读取 cacert.pem 证书 | ||
bs, err := ioutil.ReadFile(filepath.Join(path, "cacert.pem")) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
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 commentThe reason will be displayed to describe this comment to others. Learn more. bs 和 cacert 是同样的内容,不需要重复读取 |
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
certificate, err := tls.LoadX509KeyPair(filepath.Join(path, "cert.pem"), filepath.Join(path, "private.key")) | ||
pb, _ := pem.Decode(cacert) | ||
x509cert, err := x509.ParseCertificate(pb.Bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
creds := credentials.NewTLS( | ||
&tls.Config{ | ||
ServerName: serviceName, | ||
Certificates: []tls.Certificate{certificate}, | ||
RootCAs: certPool, | ||
ClientCAs: certPool, | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. 修改判断是否使用国密的逻辑,区分客户端和服务端 其中,ClientHello 结构中包含了客户端支持的加密套件,服务端根据自身的支持的加密套件和客户端支持的加密套件返回对应的加密套件协商结果。 客户端是否使用国密可以通过以下方案判断
服务端通过如下方案 |
||
certPool := x509.NewCertPool() | ||
ok := certPool.AppendCertsFromPEM(bs) | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. gmtls 中的 x509 证书兼容标准的 RSA x509 解析,同一个证书只需要加载和解析一次,可以参考官方示例 |
||
if err != nil { | ||
return nil, err | ||
} | ||
creds := gmcredentials.NewTLS( | ||
&tls.Config{ | ||
GMSupport: tls.NewGMSupport(), | ||
ServerName: serviceName, | ||
Certificates: []tls.Certificate{certificate, certificate}, | ||
RootCAs: certPool, | ||
ClientCAs: certPool, | ||
ClientAuth: tls.RequireAndVerifyClientCert, | ||
}) | ||
serverNameMap[serviceName] = creds | ||
return creds, nil | ||
} else { //非国密 | ||
certPool := defaultx509.NewCertPool() | ||
ok := certPool.AppendCertsFromPEM(bs) | ||
if !ok { | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. 通 70 行 comment |
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
creds := credentials.NewTLS( | ||
&defaulttls.Config{ | ||
ServerName: serviceName, | ||
Certificates: []defaulttls.Certificate{certificate}, | ||
RootCAs: certPool, | ||
ClientCAs: certPool, | ||
ClientAuth: defaulttls.RequireAndVerifyClientCert, | ||
}) | ||
serverNameMap[serviceName] = creds | ||
return creds, nil | ||
} | ||
|
||
} | ||
|
||
// GenerateKeyPairWithPath generate xuper net key pair | ||
|
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.
好的