第一步:生成ca、服务端、客户端证书
1. 生成ca根证书 生成ca证书私钥
openssl genrsa -out ca.key 4096
创建ca.conf 文件
[ req ] default_bits = 4096 distinguished_name = req_distinguished_name [ req_distinguished_name ] countryname = country name (2 letter code) countryname_default = cn stateorprovincename = state or province name (full name) stateorprovincename_default = jiangsu localityname = locality name (eg, city) localityname_default = nanjing organizationname = organization name (eg, company) organizationname_default = sheld commonname = common name (e.g. server fqdn or your name) commonname_max = 64 commonname_default = localhost
生成根证书签发申请文件(csr文件)
openssl req \ -new \ -sha256 \ -out ca.csr \ -key ca.key \ -config ca.conf
生成自签发根证书(crt文件)
openssl x509 \
-req \
-days 3650 \
-in ca.csr \
-signkey ca.key \
-out ca.pem2. 生成服务端证书
生成服务端私钥
openssl genrsa -out server.key 2048
创建 server.conf 文件
[ req ] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext [ req_distinguished_name ] countryname = country name (2 letter code) countryname_default = cn stateorprovincename = state or province name (full name) stateorprovincename_default = jiangsu localityname = locality name (eg, city) localityname_default = nanjing organizationname = organization name (eg, company) organizationname_default = sheld commonname = common name (e.g. server fqdn or your name) commonname_max = 64 commonname_default = localhost # 此处尤为重要,需要用该服务名字填写到客户端的代码中 [ req_ext ] subjectaltname = @alt_names [alt_names] dns.1 = localhost ip.1 = 127.0.0.1
生成服务端签发申请文件(csr文件)
openssl req \ -new \ -sha256 \ -out server.csr \ -key server.key \ -config server.conf
使用ca证书签署服务器证书
openssl genrsa -out client.key 2048
3. 生成客户端证书
生成客户端私钥
openssl genrsa -out client.key 2048
创建 client.conf 文件
[ req ] default_bits = 2048 distinguished_name = req_distinguished_name [ req_distinguished_name ] countryname = country name (2 letter code) countryname_default = cn stateorprovincename = state or province name (full name) stateorprovincename_default = jiangsu localityname = locality name (eg, city) localityname_default = nanjing organizationname = organization name (eg, company) organizationname_default = sheld commonname = common name (e.g. server fqdn or your name) commonname_max = 64 commonname_default = localhost
生成客户端端签发申请文件(csr文件)
openssl req \ -new \ -sha256 \ -out client.csr \ -key client.key \ -config client.conf
使用ca证书签署客户端器证书
openssl x509 \
-req \
-days 3650 \
-ca ca.pem \
-cakey ca.key \
-cacreateserial \
-in client.csr \
-out client.pem第二步:golang 服务端、客户端代码编写
1. 项目目录结构

2. 服务端代码:server.go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
)
type myhandler struct {
}
func (h *myhandler) servehttp(w http.responsewriter,
r *http.request) {
fmt.fprint(w, "hello, https!")
}
func main() {
pool := x509.newcertpool() // 创建证书池
cacertpath := "./cert/ca.pem"
cacrt, err := os.readfile(cacertpath) // 读取本地ca证书文件
if err != nil {
fmt.println("readfile err:", err)
return
}
pool.appendcertsfrompem(cacrt) // 将证书添加到证书池中
s := &http.server{ // 创建 http服务器实例,并设置服务器的监听地址(本例中是127.0.0.1:8088)、处理器(即上面定义的myhandler结构体)、以及tls配置。
addr: "127.0.0.1:8088",
handler: &myhandler{},
tlsconfig: &tls.config{
clientcas: pool, // 指定客户端需要验证的ca证书池(即上面创建的pool)
clientauth: tls.requireandverifyclientcert, // 要求客户端在发送请求时必须携带证书
},
}
err = s.listenandservetls("./cert/server.pem", "./cert/server.key")
if err != nil {
fmt.println("listenandservetls err:", err)
}
}3. 客户端代码:client.go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net/http"
"os"
)
func main() {
pool := x509.newcertpool() // 创建 x509.certpool,用于存储ca证书
cacertpath := "./cert/ca.pem" // 从文件中读取ca证书的内容
cacrt, err := os.readfile(cacertpath)
if err != nil {
fmt.println("readfile err:", err)
return
}
pool.appendcertsfrompem(cacrt) // 将ca证书添加到certpool中
clicrt, err := tls.loadx509keypair("./cert/client.pem", "./cert/client.key") //加载客户端证书和私钥
if err != nil {
fmt.println("loadx509keypair err:", err)
return
}
tr := &http.transport{ // 创建一个http.transport,并配置tls相关信息
tlsclientconfig: &tls.config{
rootcas: pool, // 设置根证书池
certificates: []tls.certificate{clicrt}, // 设置客户端证书和私钥
},
}
client := &http.client{transport: tr} // 创建一个http.client,并设置transport为上面创建的transport对象
resp, err := client.get("https://127.0.0.1:8088") // 使用创建的client发送get请求
if err != nil {
fmt.println("http get error:", err)
return
}
defer resp.body.close()
body, err := io.readall(resp.body) // 读取并打印响应体的内容
fmt.println(string(body))
}第三步:验证
1. 运行服务端
go run ./server/server.go

2. 运行客户端
运行客户端
go run ./client/client.go

到此这篇关于golang实现openssl自签名双向认证的详细步骤的文章就介绍到这了,更多相关golang双向认证内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论