• TLS示例开发-golang版本


    前言

    在进行项目总结的时候,领导提出有关数据安全的问题。总结会议过后,自己查阅了一下资料,发现基于CA的TLS证书认证方案是一个很好的选择,虽然项目本身也有关于数据安全的处理,但是从远不及TLS的处理方式。

    本文只介绍tls的开发,采用go语言,不会涉及到太多专业的词语。


    制作自签名证书

    初始目录如下:

    grpc-tls/
    ├── configs
    │   ├── cert # 存放证书相关的目录
    ├── cmd
    

    CA

    为了保证证书的可靠性和有效性,在这里可引入 CA 颁发的根证书的概念。CA就是专门用自己的私钥给别人进行签名的单位或者机构,其遵守 X.509 标准,即无论是客户端还是服务端都是使用CA来签发证书。

    根证书

    根证书(root certificate)是属于根证书颁发机构(CA)的公钥证书。我们可以通过验证 CA 的签名从而信任 CA ,任何人都可以得到 CA 的证书(含公钥),用以验证它所签发的证书(客户端、服务端)。

    它包含了公钥和密钥。

    CA公钥

    进入cert目录

    openssl genrsa -out ca.key 2048
    
    • openssl genrsa:生成RSA私钥,命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512

    CA秘钥(证书)

    openssl req -new -x509 -days 365 -key ca.key -out ca.pem
    
    • -x509:证书文件格式为x509,目前TLS默认只支持这种格式的证书
    • -days 365:证书有效期1年
    • -out ca.pem:生成的私钥保存到ca.pem

    要填写的信息:

    Country Name (2 letter code) [XX]:
    State or Province Name (full name) []:
    Locality Name (eg, city) [Default City]:
    Organization Name (eg, company) [Default Company Ltd]:
    Organizational Unit Name (eg, section) []:
    Common Name (eg, your name or your server's hostname) []:ca.com
    Email Address []:
    
    • 生成的过程中会要求填一些信息,除了Common Name要取一个容易区分的名字之外,其它都可以随便填写,我们在这里将它填为ca.com.

    目录

    grpc-tls/
    ├── configs
    │   ├── cert # 存放证书相关的目录
    │   	├── ca.key
    │   	└── ca.pem
    ├── cmd
    

    服务器证书相关

    服务器key

    # openssl genrsa -out server.key 2048
    或者
    openssl ecparam -genkey -name secp384r1 -out server.key
    
    • openssl genrsa:生成RSA私钥,命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512
    • openssl ecparam:生成ECC私钥,命令为椭圆曲线密钥参数生成及操作,本文中ECC曲线选择的是secp384r1

    生成 CSR(证书申请文件)

    CSR 是**Cerificate Signing Request **的英文缩写,为证书申请文件,在服务器私钥的基础上加上一些申请人的属性信息,比如我是谁,来自哪里,名字叫什么,证书适用于什么场景等的信息,然后带上进行的签名,发给CA(私下安全的方式发送),带上自己签名的目的是为了防止别人篡改文件。

    openssl req -new -key server.key -out server.csr
    

    要填写的信息:

    Country Name (2 letter code) [AU]:
    State or Province Name (full name) [Some-State]:
    Locality Name (eg, city) []:
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:
    Organizational Unit Name (eg, section) []:
    Common Name (e.g. server FQDN or YOUR name) []:domain.com
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:123456
    An optional company name []:
    
    • 生成的过程中会要求填一些信息,除了Common Name要取一个容易区分的名字之外,其它都可以随便填写,我们在这里将它填为domain.com;
    • 密码也是建议填写;
    • 注意和ca证书的不同。

    基于 CA 签发

    使用CA的公钥对申请文件进行签名

    openssl x509 -req -sha256 -CA ca.pem -CAkey ca.key -CAcreateserial -days 3650 -in server.csr -out server.pem
    
    • -sha256:生成的证书里面使用sha256作为摘要算法
    • 由于需要往生成的证书里写入签名者的信息,所以这里需要ca.pem,因为只有这里有CA的描述信息,ca.key里面只有公钥的信息。

    目录

    grpc-tls/
    ├── configs
    │   ├── cert # 存放证书相关的目录
    │   	├── ca.key
    │   	└── ca.pem
    │   	├── server.csr
    │   	└── server.key
    │   	└── server.pem
    ├── cmd
    

    客户端证书相关

    此生成的证书可用于浏览器、java、tomcat、golang等。

    客户端key

    openssl ecparam -genkey -name secp384r1 -out client.key
    

    生成CSR(证书申请书)

    openssl req -new -key client.key -out client.csr
    

    要填写的信息:

    Country Name (2 letter code) [AU]:
    State or Province Name (full name) [Some-State]:
    Locality Name (eg, city) []:
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:
    Organizational Unit Name (eg, section) []:
    Common Name (e.g. server FQDN or YOUR name) []:domain.com
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:123456
    An optional company name []:
    
    • Common Name要取一个容易区分的名字之外,填为domain.com,和服务器的CSR保持一致;
    • 密码也是建议填写;
    • 注意和ca证书的不同。

    基于CA签发

    openssl x509 -req -sha256 -CA ca.pem -CAkey ca.key -CAcreateserial -days 3650 -in client.csr -out client.pem
    

    生成客户端p12格式根证书

    该证书用于导入浏览器使用。

    openssl pkcs12 -export -clcerts -in client.pem -inkey client.key -out client.p12
    

    目录

    grpc-tls/
    ├── configs
    │   ├── cert # 存放证书相关的目录
    │   	├── ca.key
    │   	└── ca.pem # 导入浏览器使用
    │   	├── server.csr
    │   	└── server.key
    │   	└── server.pem
    │   	├── client.csr
    │   	└── client.key
    │   	└── client.pem
    │   	└── client.p12 # 导入浏览器使用
    ├── cmd
    

    证书如何验证

    下面以浏览器为例,说明证书的验证过程:

    • 在TLS握手的过程中,浏览器得到了网站的证书(.p12)

    • 打开证书,查看是哪个CA签名的这个证书(.p12)

    • 在自己信任的CA库中,找相应CA的证书(ca.pem),

    • 用CA证书里面的公钥解密网站证书上的签名,取出网站证书的校验码(指纹),然后用CA证书中摘要算法(比如sha256)算出出网站证书的校验码,如果校验码和签名中的校验码对的上,说明这个证书是合法的,且没被人篡改过

    • 读出里面的CN,对于网站的证书,里面一般包含的是域名

    • 检查里面的域名和自己访问网站的域名对不对的上,对的上的话,就说明这个证书确实是颁发给这个网站的

    • 到此为止检查通过

    如果浏览器发现证书有问题,一般是证书里面的签名者不是浏览器认为值得信任的CA,浏览器就会给出警告页面,这时候需要谨慎,有可能证书被掉包了。如访问12306网站,由于12306的证书是自己签的名,并且浏览器不认为12306是受信的CA,所以就会给警告,但是一旦你把12306的根证书安装到了你的浏览器中,那么下次就不会警告了,因为你配置了浏览器让它相信12306是一个受信的CA。


    在浏览器中导入证书

    导入证书

    • 详细步骤百度即可....

    • 个人导入client.p12证书

    • 受信任的根证书颁发机构导入ca.pem证书

    修改域名

    ca.pem这个证书是发给domain.com的,而不是127.0.0.1,所以在C:WindowsSystem32driversetchosts添加一记录:

    127.0.0.1   domain.com
    

    测试完成之后记得手动将127.0.0.1 domain.comC:WindowsSystem32driversetchosts里面删掉。


    golang服务端

    目录

    grpc-tls/
    ├── configs
    │   ├── cert # 存放证书相关的目录
    │   	├── ca.key
    │   	└── ca.pem # 导入浏览器使用
    │   	├── server.csr
    │   	└── server.key
    │   	└── server.pem
    │   	├── client.csr
    │   	└── client.key
    │   	└── client.pem
    │   	└── client.p12 # 导入浏览器使用
    ├── cmd
    │   ├── main.go
    

    main.go

    package main
    
    import (
    	"crypto/tls"
    	"crypto/x509"
    	"github.com/gin-gonic/gin"
    	"io/ioutil"
    	"log"
    	"net/http"
    	"time"
    )
    
    func main() {
    	router := gin.Default()
    	router.GET("/test", func(c *gin.Context) {
    		c.JSON(200, gin.H{
    			"message": "test",
    		})
    	})
    
    	// 启动https方式访问
    	cert, err := tls.LoadX509KeyPair("./configs/cert/server.pem", "./configs/cert/server.key")
    	if err != nil {
    		log.Fatalf("tls.LoadX509KeyPair err: %v", err)
    	}
    	certPool := x509.NewCertPool()
    	ca, err := ioutil.ReadFile("./configs/cert/ca.pem")
    	if err != nil {
    		log.Fatalf("ioutil.ReadFile err: %v", err)
    	}
    	if ok := certPool.AppendCertsFromPEM(ca); !ok {
    		log.Fatalf("certPool.AppendCertsFromPEM err")
    	}
    	ReadTimeout := time.Duration(60) * time.Second
    	WriteTimeout := time.Duration(60) * time.Second
    
    	s := &http.Server{
    		Addr:          ":8090",
    		Handler:        router,
    		ReadTimeout:    ReadTimeout,
    		WriteTimeout:   WriteTimeout,
    		MaxHeaderBytes: 1 << 20,
    		TLSConfig:&tls.Config{
    			Certificates: []tls.Certificate{cert},
    			MinVersion: tls.VersionTLS12,
    			ClientAuth:   tls.RequireAndVerifyClientCert,
    			ClientCAs:    certPool,
    		},
    	}
    
    	s.ListenAndServeTLS("./configs/cert/server.pem","./configs/cert/server.key")
    }
    
    

    测试

    在浏览器输入https://domain.com:8090/test


    参考

    SSL/TLS及证书概述

    带入gRPC:TLS 证书认证

  • 相关阅读:
    实验6 继承
    实验5 运算符重载
    实验4 类初步
    实验3 文件操作
    实验2 C++数组与指针
    实验1 C++函数
    C++程序设计实验安排
    计算机图形学课件pdf版
    《三维建模简介》课件
    《3D建模初步》参考资料
  • 原文地址:https://www.cnblogs.com/dust90/p/11207219.html
Copyright © 2020-2023  润新知