生成tls证书 Golang的tls例子
生成根证书和网站签名
名词解释
SSL: 安全套接字层 Secure Socket Layer 的缩写.
TLS: 传输层安全协议 Transport Layer Security 的缩写.
KEY: 通常指私钥(包含公钥和私钥).
PUB: 通常指公钥.
CSR: 是 Certificate Signing Request 的缩写, 即证书签名请求, 这不是证书, 可以简单理解成公钥, 生成证书时要把这个提交给权威的证书颁发机构.
CRT: 即 Certificate 的缩写, 即证书.
X.509: 是一种证书格式. 对 X.509 证书来说, 认证者总是 CA 或由 CA 指定的人, 一份 X.509 证书是一些标准字段的集合, 这些字段包含有关用户或设备及其相应公钥的信息. X.509 的证书文件, 一般以 .crt 结尾, 根据该文件的内容编码格式, 可以分为以下二种格式:
PEM: Privacy Enhanced Mail, 打开看文本格式, 以 "-----BEGIN..." 开头, "-----END..." 结尾, 内容是BASE64编码. Apache 和 UNIX 服务器偏向于使用这种编码格式.
DER: Distinguished Encoding Rules, 打开看是二进制格式, 不可读. Java 和 Windows 服务器偏向于使用这种编码格式.
OpenSSL: 相当于SSL的一个实现, 如果把SSL规范看成OO中的接口, 那么OpenSSL则认为是接口的实现. 接口规范本身是安全没问题的, 但是具体实现可能会有不完善的地方, 比如之前的 "心脏出血" 漏洞, 就是 OpenSSL 中的一个 bug.
私钥格式参见 RFC3447
==> ca.key <==
-----BEGIN RSA PRIVATE KEY-----
xxxxxx
-----END RSA PRIVATE KEY-----
==> ca.pub <==
-----BEGIN PUBLIC KEY-----
xxxxxx
-----END PUBLIC KEY-----
==> ca.csr <==
-----BEGIN CERTIFICATE REQUEST-----
xxxxxx
-----END CERTIFICATE REQUEST-----
==> ca.crt <==
-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----
生成 ca 私钥和证书
生成 ca 私钥
openssl genrsa -out ca.key 4096
从 ca 私钥提取公钥
openssl rsa -in ca.key -pubout -out ca.pub
生成 ca 证书签发请求
openssl rand -base64 100 > ~/.rnd
openssl req -new -sha256 -key ca.key -subj "/CN=ca.com" -out ca.csr
生成 ca 证书
openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt
生成网站私钥和公钥
生成网站私钥
openssl genrsa -out site.key 4096
从网站私钥提取公钥
openssl rsa -in site.key -pubout -out site.pub
生成网站证书签发请求
openssl req -new -sha256 -key site.key -subj "/CN=dotcoo.com" -out site.csr
使用 ca 私钥 签名站点证书
openssl x509 -req -sha256 -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in site.csr -out site.crt
查询状态
openssl x509 -in ./site.crt -noout -text
查看 ASN.1 格式的私钥
openssl asn1parse -l -in ca.key
参考地址
http://www.cnblogs.com/Goden/p/4639672.html https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
https
将根证书添加到本地, 双击安装, 将根证书拖拽到 受信任的根证书颁发机构
-> 证书
.
https.go
package main
import (
"io"
"log"
"net/http"
)
// hello dotcoo, the web server
func HelloServer(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "hello, dotcoo!\n")
}
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
log.Println("https://server.com:12345/hello")
http.HandleFunc("/hello", HelloServer)
log.Fatal(http.ListenAndServeTLS(":12345", "server.crt", "server.key", nil))
}
socket
socket_server.go
package main
import (
"bufio"
"crypto/tls"
"io"
"log"
"net"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
certFile := "server.crt"
keyFile := "server.key"
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
panic(err)
}
config := new(tls.Config)
config.Certificates = []tls.Certificate{cert}
ln, err := tls.Listen("tcp", ":8100", config)
if err != nil {
panic(err)
}
log.Println("127.0.0.1:8100")
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go service(conn)
}
}
func service(conn net.Conn) {
defer conn.Close()
r := bufio.NewReader(conn)
for {
line, _, err := r.ReadLine()
if err == io.EOF {
return
}
if err != nil {
log.Println(err)
return
}
n, err := conn.Write(line)
if err != nil {
log.Println(n, err)
return
}
}
}
socket_client.go
package main
import (
"crypto/tls"
"crypto/x509"
"io"
"io/ioutil"
"log"
"time"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
pemPath := "ca.crt"
config := new(tls.Config)
certs := x509.NewCertPool()
pemData, err := ioutil.ReadFile(pemPath)
if err != nil {
panic(err)
}
certs.AppendCertsFromPEM(pemData)
config.RootCAs = certs
conn, err := tls.Dial("tcp", "server.com:8100", config)
if err != nil {
panic(err)
}
defer conn.Close()
buf := make([]byte, 1024)
for {
n, err := io.WriteString(conn, time.Now().Format("2006-01-02 15:04:05\r\n"))
if err != nil {
log.Println(n, err)
break
}
n, err = conn.Read(buf)
if err != nil {
log.Println(n, err)
break
}
log.Println(string(buf[:n]))
time.Sleep(1 * time.Second)
}
}
starttls
starttls_server.go
package main
import (
"bufio"
"crypto/tls"
"io"
"log"
"net"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
ln, err := net.Listen("tcp", ":8100")
if err != nil {
panic(err)
}
log.Println("127.0.0.1:8100")
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go service(conn)
}
}
func service(conn net.Conn) {
certFile := "server.crt"
keyFile := "server.key"
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
panic(err)
}
config := new(tls.Config)
config.Certificates = []tls.Certificate{cert}
defer conn.Close()
r := bufio.NewReader(conn)
for {
line, _, err := r.ReadLine()
if err == io.EOF {
return
}
if err != nil {
log.Println(err)
return
}
n, err := conn.Write(line)
if err != nil {
log.Println(n, err)
return
}
if string(line) == "starttls" {
conn = tls.Server(conn, config)
r = bufio.NewReader(conn)
}
}
}
starttls_client.go
package main
import (
"crypto/tls"
"crypto/x509"
"io"
"io/ioutil"
"log"
"net"
"time"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
pemPath := "ca.crt"
config := new(tls.Config)
certs := x509.NewCertPool()
pemData, err := ioutil.ReadFile(pemPath)
if err != nil {
panic(err)
}
certs.AppendCertsFromPEM(pemData)
config.RootCAs = certs
config.ServerName = "server.com"
conn, err := net.Dial("tcp", "server.com:8100")
if err != nil {
panic(err)
}
defer conn.Close()
buf := make([]byte, 1024)
for i := 0; i < 100; i++ {
data := time.Now().Format("2006-01-02 15:04:05\r\n")
if i == 10 {
data = "starttls\r\n"
}
n, err := io.WriteString(conn, data)
if err != nil {
log.Println(n, err)
break
}
n, err = conn.Read(buf)
if err != nil {
log.Println(n, err)
break
}
log.Println(string(buf[:n]))
if data == "starttls\r\n" {
conn = tls.Client(conn, config)
}
time.Sleep(1 * time.Second)
}
}