生成tls证书 Golang的tls例子

2016-09-23 10:54  5404人阅读  评论 (0)

生成根证书和网站签名

名词解释

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)
  }
}