go-自籤ca證書,客戶端數字證書,服務端數字證書

和風說話的青苔發表於2020-11-13

ca.conf

# ca.conf
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
# 生成v3版本帶擴充套件屬性的證書
req_extensions = v3_req

# 設定預設域名
[ req_distinguished_name ]
# Minimum of 4 bytes are needed for common name
commonName         = www.examples.com
commonName_default = *.examples.com
commonName_max     = 64

# 設定兩位國家程式碼
# ISO2 country code only
countryName         = China
countryName_default = CN

# 設定州 或者 省的名字
# State is optional, no minimum limit
stateOrProvinceName         = Province
stateOrProvinceName_default = Beijing

# 設定城市的名字
# City is required
localityName         = City
localityName_default = Beijing

# 設定公司或組織機構名稱
# Organization is optional
organizationName         = Organization
organizationName_default = ca

# 設定部門名稱
# Organization Unit is optional
organizationalUnitName         = ca
organizationalUnitName_default = ca

# 設定聯絡郵箱
# Email is optional
emailAddress         = Email
emailAddress_default = email@example.com

# 擴充資訊配置
[ v3_req ]
#basicConstraints = CA:FALSE # 表明要簽發終端證書
basicConstraints = CA:TRUE # 表明要簽發CA證書
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

# 要配置的域名
[alt_names]
DNS.1 = www.example.com
DNS.2 = *.example.com
DNS.3 = localhost

example.com.conf

# example.com.conf
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
# 生成v3版本帶擴充套件屬性的證書
req_extensions = v3_req

# 設定預設域名
[ req_distinguished_name ]
# Minimum of 4 bytes are needed for common name
commonName         = www.examples.com
commonName_default = *.examples.com
commonName_max     = 64

# 設定兩位國家程式碼
# ISO2 country code only
countryName         = China
countryName_default = CN

# 設定州 或者 省的名字
# State is optional, no minimum limit
stateOrProvinceName         = Province
stateOrProvinceName_default = Beijing

# 設定城市的名字
# City is required
localityName         = City
localityName_default = Beijing

# 設定公司或組織機構名稱
# Organization is optional
organizationName         = Organization
organizationName_default = myzs

# 設定部門名稱
# Organization Unit is optional
organizationalUnitName         = myzs
organizationalUnitName_default = myzs

# 設定聯絡郵箱
# Email is optional
emailAddress         = Email
emailAddress_default = email@example.com

# 擴充資訊配置
[ v3_req ]
basicConstraints = CA:FALSE # 表明要簽發終端證書
#basicConstraints = CA:TRUE # 表明要簽發CA證書
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

# 要配置的域名
[alt_names]
DNS.1 = www.example.com
DNS.2 = *.example.com
DNS.3 = localhost

client.ext

extendedKeyUsage=clientAuth
# CA生成
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -config ca.conf -days 5000 -out ca.crt

# 服務端證書
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -config example.com.conf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000 -extensions v3_req -extfile example.com.conf

# 客戶端證書
openssl genrsa -out client.key 2048
openssl req -new -key client.key -config example.com.conf -out client.csr
# 1、建立檔案client.ext 內容:extendedKeyUsage=clientAuth
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile client.ext -out client.crt -days 5000 -extensions v3_req -extfile example.com.conf  # 必須要加-extensions v3_req -extfile example.com.conf

# 檢視數字證書內容
openssl x509 -text -in client.crt -noout # 檢視client.crt內容
openssl x509 -text -in server.crt -noout

在這裡插入圖片描述

在這裡插入圖片描述
server.go

package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net/http"
)

type myhandler struct {
}

func (h *myhandler) ServeHTTP(w http.ResponseWriter,
	r *http.Request) {
	fmt.Fprintf(w,
		"Hi, This is an example of http service in golang!\n")
}

func main() {
	pool := x509.NewCertPool()
	caCertPath := "ca.crt"

	caCrt, err := ioutil.ReadFile(caCertPath)
	if err != nil {
		fmt.Println("ReadFile err:", err)
		return
	}
	pool.AppendCertsFromPEM(caCrt)

	s := &http.Server{
		Addr:    ":8081",
		Handler: &myhandler{},
		TLSConfig: &tls.Config{
			ClientCAs:  pool,
			ClientAuth: tls.RequireAndVerifyClientCert,
		},
	}

	err = s.ListenAndServeTLS("server.crt", "server.key")
	if err != nil {
		fmt.Println("ListenAndServeTLS err:", err)
	}
}

client.go

package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	pool := x509.NewCertPool()
	caCertPath := "ca.crt"

	caCrt, err := ioutil.ReadFile(caCertPath)
	if err != nil {
		fmt.Println("ReadFile err:", err)
		return
	}
	pool.AppendCertsFromPEM(caCrt)

	cliCrt, err := tls.LoadX509KeyPair("client.crt", "client.key")
	if err != nil {
		fmt.Println("Loadx509keypair err:", err)
		return
	}

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			RootCAs:      pool,
			Certificates: []tls.Certificate{cliCrt},
		},
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get("https://localhost:8081")
	if err != nil {
		fmt.Println("Get error:", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))
}

相關文章