有关注我博客的同学可能对我以前的文章写过 https 和 tls 证书可能有点印象,这里我顺便贴一下以前的文章列表:

这两篇文章分别是第一篇是讲如何自己创建自授权的证书在私有环境内使用 TLS 和 https 的介绍,而第二篇文章介绍的是如何在公网环境创建一个安全的 https 站点。在写完这两篇文章之后,尤其是第一篇文章,很多同学照做之后发现似乎有些出入,这里我需要自我检讨一番,可能有些配置没有细说,导致跟着做的时候不对;另外就是步骤稍微繁琐了一点,导致有的同学会漏掉部分命令,从而导致最终出来的东西不正确。(这里顺带提一句,Comment 的效果可能不及发邮件及时)

所以,为了简化一些操作步骤,我尝试用 Go 语言进行自授权的证书生成,并且本文还将对自己生成的自授权证书进行创建一个简单的 Http Server 进行验证,完全的代码都可以在:Github 上获取。

使用 Golang 创建证书的核心其实就是一个证书的设置结构体,示例为:

// created by liqiang.io
rootTemplate := x509.Certificate{
	SerialNumber: serialNumber,
	Subject: pkix.Name{
	Organization: []string{*Organization},
	CommonName:   *CaCommonName,
	},
	NotBefore:             notBefore,
	NotAfter:              notAfter,
	KeyUsage:              x509.KeyUsageCertSign,
	ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
	BasicConstraintsValid: true,
	IsCA: true,
}

这里有几个项目需要说明一下:

然后根据这个配置生成证书:

// created by liqiang.io
derBytes, err := x509.CreateCertificate(rand.Reader, &rootTemplate, &rootTemplate, &rootKey.PublicKey, rootKey)
if err != nil {
	panic(err)
}

这个没啥好说的,值得一提的就是需要提供 key,这个 key 可以通过 ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 创建,同时,还需要提供随机数。创建完证书之后,要进行导出,然而导出并不能直接写到文件里面,而是需要进行编码:

// created by liqiang.io
certOut, err := os.Create(filename)
if err != nil {
	log.Fatalf("failed to open cert.pem for writing: %s", err)
}
if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
	log.Fatalf("failed to write data to cert.pem: %s", err)
}
if err := certOut.Close(); err != nil {
	log.Fatalf("error closing cert.pem: %s", err)
}

这样才算是完成了一个完整的证书文件,公钥私钥都齐活。这一套代码对于创建 Ca 证书和 Server/Client 证书都通用,唯一的不同就是刚才说的参数是否需要设置 IsCA 参数。

Http server 验证

当生成完证书之后,验证肯定必不可少,而我们也可以很简单得通过 Go 代码快速得创建一个 Https Server 进行验证,例如:

func main() {
	// created by https://liqiang.io
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
		w.Write([]byte("This is an example server.\n"))
	})
	srv := &http.Server{
		Addr:         "10.0.0.4:1443",
		Handler:      mux,
		TLSConfig:    &tls.Config{},
		TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
	}
	log.Fatal(srv.ListenAndServeTLS("gen/server.pem", "gen/server.key"))
}

然后直接运行起来就可以,通过浏览器访问: https://liqiang.io 就可以很简单得看到了一个 Https 的访问页面了。

小结

本文简单得总结了一下如何利用 Go 编程语言进行自授权证书的创建,并且给出了一个简单的 https server 进行验证自授权证书,虽然简单,但是这确实后续我博客中很多内容的基础,希望对你有所帮助。