学习go语言编程之安全编程

发布时间 2023-08-15 21:53:38作者: nuccch

数据加密

对称加密

采用单密钥的加密算法,称为对称加密。
常见的单密钥加密算法有DESAESRC4等。
在对称加密中,私钥不能暴露,否则在算法公开的情况下,数据等同于明文。

非对称加密

采用双密钥的加密算法,称为非对称加密。
在该系统中,私钥和公钥都可以被用作加密或者解密,但是用私钥加密的明文,必须要用对应的公钥解密;用公钥加密的明文,必须用对应的私钥解密。
常见的双密钥加密算法有RSA等。
在非对称加密中,公钥是公开的,私钥是保密的。这样任何人都可以把自己的信息通过公钥和算法加密,然后发送给公钥的发布方,只有公钥发布方(公钥发布方拥有私钥)才能解开密文。

哈希加密

使用哈希算法可以实现加密后不可解密的需求。
哈希算法是一种从任意数据中创建固定长度摘要信息的办法,对于不同的数据,要求产生的摘要信息也是唯一的。
常见的哈希算法包括MD5SHA-1等。

数字签名

数字签名,是指用于标记数字文件拥有者、创造者、分发者身份的字符串。
常用的数字签名采用了非对称加密。
例如,A公司发布了一个可执行文件,称为AProduct.exe,A在AProduct.exe中加入了A公司的数字签名。A公司的数字签名是用A公司的私钥加密了AProduct.exe文件的哈希值,我们得到打过数字签名的AProduct.exe后,可以查看数字签名。这个过程实际上是用A公司的公钥解密了文件哈希值,从而可以验证两个问题:AProduct.exe是否由A公司发布,AProduct.exe是否被篡改。

数字证书

通过数字证书可以实现非对称加密。
首次使用U盾的时候,初始化过程即是向U盾中下载数字证书。数字证书中包含了银行的公钥,有了公钥之后,网银就可以用公钥加密我们提供给银行的信息,这样只有银行才能用对应的私钥得到我们的信息,确保安全。

PKI体系

PKI,全称:公钥基础设施。
是使用非对称加密理论,提供数字签名、加密、数字证书等服务的体系,一般包括权威认证机构(CA)、数字证书库、密钥备份及恢复系统、证书作废系统、应用接口(API)等。

Golang的哈希函数

Go提供了MD5SHA-1等几种哈希函数,如下示例。

// 对字符串计算哈希值
TestString := "Hello, World!"

// 使用MD5哈希
md5Hash := md5.New()
md5Hash.Write([]byte(TestString))
result := md5Hash.Sum([]byte(""))
fmt.Printf("%x\n", result) // 输出:65a8e27d8879283831b664bd8b7f0ad4

// 使用SHA-1哈希
sha1Hash := sha1.New()
sha1Hash.Write([]byte(TestString))
result = sha1Hash.Sum([]byte(""))
fmt.Printf("%x\n", result) // 输出:0a0a9f2a6772942557ab5355d76af442f8f65e01
// 对文件内容计算哈希值
TestFile := "123.txt" // 文件内容:Hello, World!
f, err := os.Open(TestFile)
if err != nil {
    fmt.Println("Open file failed: ", err)
    return
}

// 计算MD5哈希
md5Hash := md5.New()
io.Copy(md5Hash, f)
result := md5Hash.Sum([]byte(""))
fmt.Printf("%x\n", result) // 输出:65a8e27d8879283831b664bd8b7f0ad4

// 计算SHA-1哈希
sha1Hash := sha1.New()
io.Copy(sha1Hash, f)
result = sha1Hash.Sum([]byte(""))
fmt.Printf("%x\n", result) // 输出:da39a3ee5e6b4b0d3255bfef95601890afd80709

加密通信

一般的HTTPS是基于SSL(Secure Sockets Layer)协议实现加密通信。

加密通信流程

如下流程是SSL/TLS的工作方式:
(1) 在浏览器中输入HTTPS协议的网址
(2) 服务器向浏览器返回证书
(3) 浏览器验证证书合法性
(4) 浏览器使用证书中的公钥加密一个随机对称密钥,并将加密后的密钥和使用密钥加密后的请求URL一起发送到服务器
(5) 服务器用私钥解密随机对称密钥,并用获取的密钥解密加密的请求URL
(6) 服务器把用户请求的网页用密钥加密,并返回给用户
(7) 用户浏览器用密钥解密服务器发来的网页数据,并将其显示出来

总结起来就是:浏览器与服务器之间通过非对称加密的方式交换对称加密密钥,数据内容使用对称加密算法加密后传输。

支持HTTPS的Web服务器

const content = "Hello,World!"

func rootHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	w.Header().Set("Content-Length", fmt.Sprint(len(content)))
	w.Write([]byte(content))
}

func main() {
	fmt.Println("支持https的Web服务器")
	http.HandleFunc("/", rootHandler)
	http.ListenAndServeTLS(":8080", "chench.crt", "chench.key", nil) // chench.crt和chench.key分别是自签名的证书和KEY文件
}

启动之后在浏览器中需要以HTTPS协议来访问:https://localhost:8080/

支持HTTPS的文件服务器

func main() {
	fmt.Println("支持HTTPS的文件服务器")
	h := http.FileServer(http.Dir("."))
	http.ListenAndServeTLS(":8001", "chench.crt", "chench.key", h) // chench.crt和chench.key分别是自签名的证书和KEY文件
}

启动之后以HTTPS协议访问:https://localhost:8001/

需要注意的是,SSL/TLS协议只能运行于TCP之上,不能在UDP上工作,且SSL/TLS位于TCP与应用层协议之间,因此所有基于TCP的应用层协议都可以透明地使用SSL/TLS为自己提供安全保障。
所谓透明地使用是指既不需要了解细节,也不需要专门处理该层的包,比如封装、解封等。