使用Bcrypt实现加密或验证登录密码
Bcrypt 就是一款加密工具,它生成的密文是60位的,而且每次加密生成的值是不一样的。MD5 加密后的值是32位的,且每次加密后的密文都是一样的。 保存密码,一般我们都推荐使用 Bcrypt 进行加密,而不使用 MD5。 从安全上讲,用户密码一般都是要经过加密(而且不能被解密)后才存储于数据库中。
虽然MD5算法不可逆,然而每次使用MD5生成的字符串都是固定的,这就给暴力破解留下了余地。
如果使用Bcrypt算法加密,那么每次生成的字符串都是不同的,这样产生的密文基本无法破解。Java语言的spring-security 框架内置了BCryptPasswordEncoder来实现Bcrypt加密。当然Go也提供了包golang.org/x/crypto/bcrypt用来实现Bcrypt加密。
- Bcrypt 加密后的值举例:
比如加密 admin, 两次结果不一样,但都以 $2a 开头:
$2a$10$cL3WHWi3/x96MII1pwm4NOMRESxbAHnImp.tV5AMIJCneIkp2IAF2
$2a$10$P1zZnMm8/KYVseSkkfh0T.i2cVwydZ5L/5rZEALWCo3f9TmVLmM9q
加密 123456:
$2a$10$wtJie2Wc93SqCCri5u/f4uZX7ATSSyMxlrCTEkPmNHLl9Oa0QdLim
- MD5 加密后的值举例:
比如加密 admin, MD5两次结果都一样 21232f297a57a5a743894a0e4a801fc3 21232f297a57a5a743894a0e4a801fc3
加密 123456: e10adc3949ba59abbe56e057f20f883e
初始化项目
(1) 创建一个 pwd_demo 的目录。
$ mkdir pwd_demo
(2) 使用 go mod 命令来管理包,设置项目的包名为 pwd_demo:
$ mkdir pwd_demo
$ go mod init pwd_demo
该命令会创建一个 go.mod 的文件,用于记录引入的包版本,类似于 node 的 package.json 或 php 的 composer.json 文件。
(3) 创建一个 main.go 文件:
package main
import (
"fmt"
)
func main() {
fmt.Println("=> hi password!")
}
(4) 运行代码
$ go run main.go
启动正常。
编写 utils 包 在 go 语言中,一个包就是一个目录,即同一个目录下的同级的所有go文件应该属于一个包。
这里我们创建一个 utils 目录,并将包名命名为 utils (即和目录名相同,不相同也可以)。
(1) 创建一个 utils 目录, 并创建一个 pwd.go 文件:
$ mkdir utils
$ cd utils
$ touch pwd.go
文件 pwd.go 代码如下: // 密码加密: pwdHash 同PHP函数 password_hash() // 密码验证: pwdVerify 同PHP函数
package utils
import "golang.org/x/crypto/bcrypt"
func PasswordHash(pwd string) (string, error) {
bytes, err := bcrypt.GenerateFrompwd([]byte(pwd), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(bytes), err
}
password_verify()
func PasswordVerify(pwd, hash string) bool {
err := bcrypt.CompareHashAndpwd([]byte(hash), []byte(pwd))
return err == nil
}
执行测试用例:
$ go test -v utils/pwd_test.go utils/pwd.go
按照提示,安装 crypto/bcrypt 包:
$ go get golang.org/x/crypto/bcrypt
像 md5 加密方法,在Go自带的包里都有,即 “crypto/md5” 。 但是自带的包里没有 bcrypt 机密库,在其 golang.org/x/crypto 加密扩展包里有,所以需要手动下载。
## 语言自带的
import "crypto/md5"
## 扩展子模块里,需要自己下载
import "golang.org/x/crypto/bcrypt"
如果不能下载,请使用 goproxy.io :
# 配置 GOPROXY 环境变量
export GOPROXY=https://goproxy.io,direct