前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go-https的简单实现

go-https的简单实现

原创
作者头像
fnatic
修改2022-07-22 17:06:44
24.6K0
修改2022-07-22 17:06:44
举报
文章被收录于专栏:fnatic的区块链fnatic的区块链

HTTPS的一种简单实现

生成密钥、证书

第一步,为服务器端和客户端准备公钥、私钥

生成服务器端私钥

代码语言:txt
复制
openssl genrsa -out server.key 1024

生成服务器端公钥

代码语言:txt
复制
openssl rsa -in server.key -pubout -out server.pem

生成客户端私钥

代码语言:txt
复制
openssl genrsa -out client.key 1024

生成客户端公钥

代码语言:txt
复制
openssl rsa -in client.key -pubout -out client.pem

第二步,生成 CA 证书

生成 CA 私钥

代码语言:txt
复制
openssl genrsa -out ca.key 1024

X.509 Certificate Signing Request (CSR) Management.

代码语言:txt
复制
openssl req -new -key ca.key -out ca.csr

X.509 Certificate Data Management.

代码语言:txt
复制
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

在执行第二步时

Common Name (e.g. server FQDN or YOUR name) []: 这一项,是最后可以访问的域名,为了方便测试,写成 test.com

如果想通过IP直接访问而不想通过域名,在创建服务端证书时:用如下语句:

代码语言:txt
复制
openssl genrsa -out server.key 2048
 
openssl req -new -key server.key -subj "/CN=192.168.1.10" -out server.csr
 
echo subjectAltName = IP:192.168.1.10 > extfile.cnf
 
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out server.crt -days 5000

第三步,生成服务器端证书和客户端证书

服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件

代码语言:txt
复制
openssl req -new -key server.key -out server.csr

向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书

代码语言:txt
复制
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt

client 端

代码语言:txt
复制
openssl req -new -key client.key -out client.csr

client 端到 CA 签名

代码语言:txt
复制
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt

第四步,客户端机器添加test.com域名

代码语言:txt
复制
sudo vim /etc/hosts

添加服务端的ip信息对应的域名:192.168.1.100 test.com

源码实现

服务端代码

代码语言:javascript
复制
package main

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

type myhandler struct {
}

func (h *myhandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("This is an example server\n"))
}

func getHandler(w http.ResponseWriter, r *http.Request)  {
    fmt.Fprintf(w, "hello, this is https get ")
}

func postHandler(w http.ResponseWriter, r *http.Request)  {
    body, _ := ioutil.ReadAll(r.Body)
    r.Body.Close()
    body_str := string(body)
    fmt.Println(body_str)
    //ret, _ := json.Marshal(user)
    ret := "{\"code\":200}"
    fmt.Fprint(w, string(ret))
}

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)
    
    server := http.NewServeMux()
    server.HandleFunc("/get",getHandler)
    server.HandleFunc("/post",postHandler)
    
    s := &http.Server{
        Addr:    ":8088",
        //Handler: &myhandler{},
        Handler: server,
        TLSConfig: &tls.Config{
            ClientCAs:  pool,
            ClientAuth: tls.RequireAndVerifyClientCert,
        },  
    }
    
    log.Printf("About to listen on 10443.Go to https://127.0.0.1:8088")
    err = s.ListenAndServeTLS("server.crt", "server.key")
    if err != nil {
        log.Fatal(err)
    }   
}

客户端代码

代码语言:javascript
复制
package main

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

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},
            InsecureSkipVerify: true,//客户端关闭对服务端的验证
        },
    }
    client := &http.Client{Transport: tr}
    jsonStr := "{\"name\":\"wang\",\"age\":29}"
    req := bytes.NewBuffer([]byte(jsonStr))
    body_type := "application/json;charset=utf-8"
    resp, err := client.Post("https://test.com:8088/post",body_type,req)
    if err != nil {
        fmt.Println("Get error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HTTPS的一种简单实现
  • 生成密钥、证书
    • 第一步,为服务器端和客户端准备公钥、私钥
      • 第二步,生成 CA 证书
        • 第三步,生成服务器端证书和客户端证书
          • 第四步,客户端机器添加test.com域名
          • 源码实现
            • 服务端代码
              • 客户端代码
              相关产品与服务
              腾讯云区块链服务平台 TBaaS
              腾讯云区块链服务平台(Tencent Blockchain as a Service,简称TBaaS)致力于打造全球领先的企业级区块链技术平台,帮助客户、开发者及合作伙伴轻松创建和管理可托管、可扩展的区块链网络,助力产业协同发展。TBaaS 支持长安链·ChainMaker、Hyperledger Fabric等区块链底层平台,简化部署、运维及开发流程,实现业务快速上链,提升链上治理效率。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档