GO实现数字证书HTTPS双向认证
HTTPS知识点全部的分析代码 anli.zip DOWNLOAD
本案例证书双向的客户端生成有点问题 无法校验成功
报错
2021/10/04 11:00:47 Get “https://localhost:8849”: remote error: tls: bad certificate
服务器
-分析流程
1. 注册client ca证书 - 读取client的ca证书 - 创建ca池 - 把client 的 ca 添加到ca池 2. 配置tls ==> cfg 3. 创建http server, 使用cfg 4. 启动http server,启动时加载自己的证书, 启动时使用tls
客户端
1. 注册给服务器颁发证书的ca - 读取ca证书 - 把ca的证书添加到ca池中 1.5 加载客户端的证书和秘钥 ==> clientCert(与单向认证比较增加代码) 2. 配置tls, ==》 增加clientCert(与单向认证比较增加代码) 3.创建http client 4. client发起请求 5. 打印返回值
https-server.go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
// 注册读取client CA证书
caInfo,err := ioutil.ReadFile("./client.pem")
if err != nil{
log.Fatal(err)
}
//创建CA池
certPool := x509.NewCertPool()
//把client的ca添加到ca池
certPool.AppendCertsFromPEM(caInfo)
//配置tls
cfg := tls.Config{
// 我们要认证client, 需要两个字段
// ClientAuth determines the server's policy for
// TLS Client Authentication. The default is NoClientCert.
//ClientAuth ClientAuthType
// const (
// NoClientCert ClientAuthType = iota
// RequestClientCert
// RequireAnyClientCert
// VerifyClientCertIfGiven
// RequireAndVerifyClientCert
//)
ClientAuth: tls.RequireAndVerifyClientCert, //设置服务器认证客户端
ClientCAs: certPool,//客户端的ca池填充在这里
}
//使用cfg创建hhtpserver
server := http.Server{
Addr: ":8849",
//Handler: nil,
Handler: &myhandler{},
TLSConfig: &cfg,
}
fmt.Println("准备启动服务器")
err = server.ListenAndServeTLS("./server.pem","./server.key")
if err != nil{
log.Fatal(err)
}
}
type myhandler struct {
}
//注意 ServeHTTP 大小写不能写错
func (h myhandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Println("ServeHTTP called!")
w.Write([]byte("Hello World"))
}
https-client
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
//注册给服务器颁发证书的ca
//读取CA证书
caInfo,err := ioutil.ReadFile("./server.pem")
if err != nil{
log.Fatal(err)
}
//把CA证书添加到CA池中
certPool := x509.NewCertPool()
//添加
certPool.AppendCertsFromPEM(caInfo)
//加载客户端的证书和秘钥 <与单向认证代码不同的区域>
clientCert,err := tls.LoadX509KeyPair("./client.pem","./client.key")
if err != nil{
log.Fatal(err)
}
//配置cls <与单向认证代码不同的区域>
cfg := tls.Config{
//服务器ca池
RootCAs: certPool,
//客户端证书
Certificates: []tls.Certificate{clientCert},
}
//创建http
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &cfg,
},
}
//发送client请求
response,err := client.Get("https://localhost:8849")
if err != nil{
log.Fatal(err)
}
defer response.Body.Close()
bodyInfo,err :=ioutil.ReadAll(response.Body)
if err != nil{
log.Fatal(err)
}
fmt.Printf("body info:%s\n",bodyInfo)
fmt.Printf("State:%s\n",response.Status)
}