百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

golang 实现https双向认证

bigegpt 2024-08-24 23:11 2 浏览

实现https双向认证

一、什么是https?

日常开发中大家可能接触最多的都是http协议, 说到http协议也不得不提到TCP/IP协议以及计算机网络中tcp/ip五层与OCI7层架构模型有关, http(超文本传输协议)用户客户端和服务端之间的通信, 位于tcp/ip五层协议中最上层传输层, http传输过程中都是明文传输, 易引起安全问题, 所有诞生了https协议。

HTTPS协议 = HTTP协议 + SSL/TLS协议, 在HTTPS数据传输的过程中, 需要用SSL/TLS对数据进行加密和解密, 需要用HTTP对加密后的数据进行传输, 由此可以看出HTTPS是由HTTP和SSL/TLS一起合作完成的。

SSL的全称是Secure Sockets Layer, 即安全套接层协议, 是为网络通信提供安全及数据完整性的一种安全协议。SSL协议在1994年被Netscape发明, 后来各个浏览器均支持SSL, 其最新的版本是3.0

二、加密算法

2.1 TLS/SSL的功能主要依赖三类算法实现:散列函数 Hash、对称加密和非对称加密, 其利用非对称加密实现身份认证和密钥协商, 对称加密算法采用协商的密钥对数据加密, 基于散列函数验证信息的完整性(对于三种加密算法含义这里就不一一概述), 而在TLS/SSL加密算法中还会涉及一下几个关键概念:

密钥:改变密码行为的数字化参数。

对称密钥加密系统:编 / 解码使用相同密钥的算法。

不对称密钥加密系统:编 / 解码使用不同密钥的算法。

公开密钥加密系统:一种能够使数百万计算机便捷地发送机密报文的系统。

数字签名:用来验证报文未被伪造或篡改的校验和。

数字证书:由一个可信的组织验证和签发的识别信息。

2.2 TLS的基本工作方式是,客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥, 然后对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取。

2.3 https通信过程中数字证书概览:

ca.pem 根证书, 由根证书颁发客户端和服务端证书

client.pem 客户端证书

client-key.pem 客户端秘钥

server.pem 服务端证书

server-key.pem 服务端秘钥

三、如何自签名证书?

3.1 目前自颁发证书工具有两类, 一是使用openssl 插件生成证书, 二是通过cfssl插件生成证书, 本例采用cfssl 工具生成证书

3.2 cfssl是一款由golang编写的证书生成工具, 官网地址:https://github.com/cloudflare/cfssl

安装步骤:

@tips: 该方法需要安装golang环境,如果没有golang请参照二进制包安装方式

> # go get -u github.com/cloudflare/cfssl/cmd/cfssl
> # go get -u github.com/cloudflare/cfssl/cmd/cfssljson

@tips windows环境需要将gopath下bin目录添加path环境中方可执行cfssl命令

查看安装是否成功:

> # cfssl

3.3 创建CA证书

> # mkdir ssl & cd ssl
> # cfssl print-defaults config > ca-config.json
> # cfssl print-defaults csr > ca-csr.json

然后修改ca-config.json文件

> # vim ca-config.json
{
"signing": {
"default": {
"expiry": "43800h"
},
"profiles": {
"server": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}

修改 expiry 值为 43800h

## 生成ca 证书
> # mkdir ca
> # cfssl gencert -initca ca-csr.json | cfssljson -bare ca/ca -

3.4 创建serverd端证书

> # mkdir server
> # cfssl print-defaults csr > server.json
## 修改server.json
{
"CN": "Server",
"hosts": [
"localhost",
"127.0.0.1"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"L": "SH",
"ST": "SH"
}
]
}
## 签发server端证书
> # cfssl gencert -ca=ca/ca.pem -ca-key=ca/ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server/server

注意: 其中 -profile=server 来自于配置文件 ca-config.json profiles 属性值

3.5 创建客户端证书:

> # mkdir client
> # cfssl print-defaults csr > client.json
## 修改client.json
{
"CN": "Client",
"hosts": [],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CN",
"L": "SH",
"ST": "SH"
}
]
}
## 生成客户端证书和私钥
> # cfssl gencert -ca=ca/ca.pem -ca-key=ca/ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client/client

注意: 其中 -profile=client 来自于配置文件 ca-config.json profiles 属性值

3.6 检验生成的证书是否和配置相符合:

> # cd
> # openssl x509 -in ca.pem -text -noout
> # cd ..
> # cd server
> # openssl x509 -in server.pem -text -noout
> # cd ..
> # cd client
> # openssl x509 -in client.pem -text -noout

四 golang实现https双向认证

实例1: https双向认证

server端代码实现:

server.go

package main
import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)
type Cert struct {
    K8sAgentCrtPath string
    K8sAgentServerCertPath string
    K8sAgentKeyPath string
}
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w,
    "Hi, This is an example of https service in golang!")
}
func main() {
    cert := Cert{
    K8sAgentCrtPath: "ca/ca.pem",
    K8sAgentServerCertPath: "server/server.pem",
    K8sAgentKeyPath: "server/server-key.pem",
    }
    // ssl 双向检验
    pool := x509.NewCertPool()
    // 根证书
    crt, err := ioutil.ReadFile(cert.K8sAgentCrtPath)
    if err != nil {
    log.Fatalln("读取证书失败!", err.Error())
    }
    pool.AppendCertsFromPEM(crt)
    http.HandleFunc("/", handler)
    s := &http.Server{
        Addr: ":8080",
        TLSConfig: &tls.Config{
        ClientCAs: pool,
        ClientAuth: tls.RequireAndVerifyClientCert, // 检验客户端证书
    },
    }
    log.Fatal(s.ListenAndServeTLS(cert.K8sAgentServerCertPath, cert.K8sAgentKeyPath)) // 服务端证书和服务端秘钥
}

client.go

package main
import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)
type Cert struct {
    K8sAgentCrtPath string
    ClientCrt string
    ClientKey string
}
func main() {
    cert := Cert{
        K8sAgentCrtPath: "ca/ca.pem",
        ClientCrt: "client/client.pem",
        ClientKey: "client/client-key.pem",
    }
    pool := x509.NewCertPool()
    caCrt, err := ioutil.ReadFile(cert.K8sAgentCrtPath) // 根证书
    if err != nil {
        log.Fatal("read ca.crt file error:", err.Error())
    }
    pool.AppendCertsFromPEM(caCrt)
    cliCrt, err := tls.LoadX509KeyPair(cert.ClientCrt, cert.ClientKey) // 客户端证书 和 客户端秘钥
    if err != nil {
        log.Fatalln("LoadX509KeyPair error:", err.Error())
    }
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{
            RootCAs: pool,
            Certificates: []tls.Certificate{cliCrt},
        },
    }
    client := &http.Client{Transport: tr}
    resp, err := client.Get("https://127.0.0.1:8080/")
    if err != nil {
        panic(err.Error())
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}
> # go run server.go
> # go run client.go
Hi, This is an example of https service in golang!

实例2: 搭建https服务

> # http.go

package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "这是一个https请求")
}
func main() {
		http.HandleFunc("/", handler)
    // err := http.ListenAndServeTLS(":8081", "server.crt", "server.key", nil)
    // 证书的文件名称可能有出入
    err := http.ListenAndServeTLS(":8081", "server/server.pem", "server/server-key.pem", nil)
    if err != nil {
        fmt.Println(err)
		}
}
> # curl -k https://112.74.106.92:8081/
这是一个https请求

注意: -k 忽略证书警告

项目目录结构

> # cd /data/ssl
> # tree
.
├── ca
│   ├── ca.csr
│   ├── ca-key.pem
│   └── ca.pem
├── ca-config.json
├── ca-csr.json
├── client
│   ├── client.csr
│   ├── client-key.pem
│   └── client.pem
├── client.go
├── client.json
├── go.mod
├── http.go
├── server
│   ├── server.csr
│   ├── server-key.pem
│   └── server.pem
├── server.go
└── server.json
3 directories, 17 files

五 使用openssl生成server.crt和server.key文件供程序使用

生成秘钥文件

> # openssl genrsa -out server.key 2048

生成证书文件

> # openssl req -new -x509 -key server.key -out server.crt -days 365
......
Common Name (eg, your name or your server's hostname) []:localhost
......

提示: 指定hostname的名称, 其他随便写或留空

实例3: 搭建https服务

http.go

package main
import (
    "fmt"
    "net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "这是一个https请求")
}
func main() {
    http.HandleFunc("/", handler)
    // 证书的文件名称可能有出入
    err := http.ListenAndServeTLS(":8081", "server.crt", "server.key", nil)
    // err := http.ListenAndServeTLS(":8081", "server/server.pem", "server/server-key.pem", nil)
    if err != nil {
      fmt.Println(err)
    }
}

> # curl -k https://112.74.106.92:8081/

这是一个https请求

相关推荐

AI「自我复制」能力曝光,RepliBench警示:大模型正在学会伪造身份

科幻中AI自我复制失控场景,正成为现实世界严肃的研究课题。英国AISI推出RepliBench基准,分解并评估AI自主复制所需的四大核心能力。测试显示,当前AI尚不具备完全自主复制能力,但在获取资源...

【Python第三方库安装】介绍8种情况,这里最全看这里就够了!

**本图文作品主要解决CMD或pycharm终端下载安装第三方库可能出错的问题**本作品介绍了8种安装方法,这里最全的python第三方库安装教程,简单易上手,满满干货!希望大家能愉快地写代码,而不要...

pyvips,一个神奇的 Python 库!(pythonvip视频)

大家好,今天为大家分享一个神奇的Python库-pyvips。在图像处理领域,高效和快速的图像处理工具对于开发者来说至关重要。pyvips是一个强大的Python库,基于libvips...

mac 安装tesseract、pytesseract以及简单使用

一.tesseract-OCR的介绍1.tesseract-OCR是一个开源的OCR引擎,能识别100多种语言,专门用于对图片文字进行识别,并获取文本。但是它的缺点是对手写的识别能力比较差。2.用te...

实测o3/o4-mini:3分钟解决欧拉问题,OpenAI最强模型名副其实!

号称“OpenAI迄今为止最强模型”,o3/o4-mini真实能力究竟如何?就在发布后的几小时内,网友们的第一波实测已新鲜出炉。最强推理模型o3,即使遇上首位全职提示词工程师RileyGoodsid...

使用Python将图片转换为字符画并保存到文件

字符画(ASCIIArt)是将图片转换为由字符组成的艺术作品。利用Python,我们可以轻松实现图片转字符画的功能。本教程将带你一步步实现这个功能,并详细解释每一步的代码和实现原理。环境准备首先,你...

5分钟-python包管理器pip安装(python pip安装包)

pip是一个现代的,通用、普遍的Python包管理工具。提供了对Python包的查找、下载、安装、卸载的功能,是Python开发的基础。第一步:PC端打开网址:选择gz后缀的文件下载第二步:...

网络问题快速排查,你也能当好自己家的网络攻城狮

前面写了一篇关于网络基础和常见故障排查的,只列举了工具。没具体排查方式。这篇重点把几个常用工具的组合讲解一下。先有请今天的主角:nslookup及dig,traceroute,httping,teln...

终于把TCP/IP 协议讲的明明白白了,再也不怕被问三次握手了

文:涤生_Woo下周就开始和大家成体系的讲hadoop了,里面的每一个模块的技术细节我都会涉及到,希望大家会喜欢。当然了你也可以评论或者留言自己喜欢的技术,还是那句话,希望咱们一起进步。今天周五,讲讲...

记一次工控触摸屏故障的处理(工控触摸屏维修)

先说明一下,虽然我是自动化专业毕业,但已经很多年不从事现场一线的工控工作了。但自己在单位做的工作也牵涉到信息化与自动化的整合,所以平时也略有关注。上一周一个朋友接到一个活,一家光伏企业用于启动机组的触...

19、90秒快速“读懂”路由、交换命令行基础

命令行视图VRP分层的命令结构定义了很多命令行视图,每条命令只能在特定的视图中执行。本例介绍了常见的命令行视图。每个命令都注册在一个或多个命令视图下,用户只有先进入这个命令所在的视图,才能运行相应的命...

摄像头没图像的几个检查方法(摄像头没图像怎么修复)

背景描述:安防监控项目上,用户的摄像头运行了一段时间有部分摄像头不能进行预览,需要针对不能预览的摄像头进行排查,下面列出几个常见的排查方法。问题解决:一般情况为网络、供电、设备配置等情况。一,网络检查...

小谈:必需脂肪酸(必需脂肪酸主要包括)

必需脂肪酸是指机体生命活动必不可少,但机体自身又不能合成,必需由食物供给的多不饱和脂肪酸(PUFA)。必需脂肪酸主要包括两种,一种是ω-3系列的α-亚麻酸(18:3),一种是ω-6系列的亚油酸(18:...

期刊推荐:15本sci四区易发表的机械类期刊

  虽然,Sci四区期刊相比收录在sci一区、二区、三区的期刊来说要求不是那么高,投稿起来也相对容易一些。但,sci四区所收录的期刊中每本期刊的投稿难易程度也是不一样的。为方便大家投稿,本文给大家推荐...

be sick of 用法考察(be in lack of的用法)

besick表示病了,做谓语.本身是形容词,有多种意思.最通常的是:生病,恶心,呕吐,不适,晕,厌烦,无法忍受asickchild生病的孩子Hermother'sverysi...