golang客户端使用证书
1 关于密匙
CAFilePath = `路径path\client.crt`
/*
这个key需要去掉密码访问否则: tls: failed to parse private key
使用openssl去掉密码的命令:
openssl rsa -in client.key -out clientno.key
*/
KeyFilePath = `路径path\clientno.key`
2 代码
const (
CAFilePath = `路径path\client.crt`
KeyFilePath = `路径path\clientno.key`//无密码的key
ServerAddr = "192.168.1.111:3459"
)
func Start() {
crt, err := tls.LoadX509KeyPair(CAFilePath, KeyFilePath)
if err != nil {
fmt.Println("LoadX509KeyPair failure:", err.Error())
}
// golang中如果不加这个,会在加载证书的时候校验证书,一些证书生成不规范,则会出现各种报错,例如: x509: certificate signed by unknown authority....所以 这里InsecureSkipVerify: true 还是跳过本地验证
//
tlsConfig := &tls.Config{InsecureSkipVerify: true}
tlsConfig.Certificates = []tls.Certificate{crt}
// Time returns the current time as the number of seconds since the epoch.
// If Time is nil, TLS uses time.Now.
tlsConfig.Time = time.Now
// Rand provides the source of entropy for nonces and RSA blinding.
// If Rand is nil, TLS uses the cryptographic random reader in package
// crypto/rand.
// The Reader must be safe for use by multiple goroutines.
tlsConfig.Rand = rand.Reader
conn, err := tls.Dial("tcp", ServerAddr, tlsConfig)
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
fmt.Println("2222222222222222")
wbuf := []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}
rbuf := make([]byte, 1024)
conn.Write(wbuf)
l, e := conn.Read(rbuf)
fmt.Println("l=", l, "e:", e)
}
3 其他方式,这个没有跑成功,
// l= 0 e: remote error: tls: bad certificate
// l= 0 e= remote error: tls: bad certificate
func StartX(serverAddr, serverName string, caFilePath string) net.Conn {
ca, err := ioutil.ReadFile(caFilePath)
if err != nil {
log.Fatalln(err)
}
certpool := x509.NewCertPool()
ok := certpool.AppendCertsFromPEM(ca)
if !ok {
log.Fatalln("load root caes failed")
}
// https://blog.csdn.net/weixin_30301449/article/details/101851985
// x509: cannot validate certificate for 192.168.1.111 because it doesn't contain any IP SANs
// 此处说明,我们不能简单通过 -subj "/CN=[IP]" 实现 CSR 中包含域名,Server证书不规范
// InsecureSkipVerify: true
// ServerName: serverName会验证跟证书配置的允许的ip或者域名.如果证书不规范,会报不匹配
tlscfg := tls.Config{RootCAs: certpool, ServerName: serverName, InsecureSkipVerify: true} //tls.Config{RootCAs: certpool, ServerName: serverName} //
conn, err := tls.Dial("tcp", serverAddr, &tlscfg)
if err != nil {
log.Fatalln(err)
}
wbuf := []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}
rbuf := make([]byte, 1024)
conn.Write(wbuf)
l, e := session.conn(rbuf)
fmt.Println("l=", l, "e:", e)
}
这串代码没有调试好,如果你也遇到这样的问题,建议换个方式. 尝试使用2的代码
其他
openssl 使用
- 将key转为无密码的key,方便go使用
openssl rsa -in client.key -out clientno.key
- 测试证书
// 开启一个证书验证服务 3459是端口,需要输入key的密码
openssl s_server -accept 3459 -cert server.crt -key server.key
// 开启客户端测试验证证书
openssl s_client -connect 127.0.0.1:2009 -cert client.crt -key client.key
或者
openssl s_client -connect 127.0.0.1:2009
服务端和客户端建立连接后,可以在控制台发送一次数据,用来验证
该服务端是一个直肠子,如果有一个客户端连接着,第二个客户端要等第一个断开后建立连接
希望可以帮助到你,起码节省很多调试时间.
Openssl的官方网站没有安装包.可以搜索其他地方提供的安装包,建议还是找个靠谱的.