(转)Go实现随机加盐密码认证
原文:https://juejin.cn/post/7068192471498358821
为什么要加密
人们往往有使用同一密码的习惯, 为了防止数据库意外泄露/破坏和出于保护用户隐私的目的, 不应在数据库里存入用户密码明文
实现
代码
scss
复制代码
package main
import (
"fmt"
"golang.org/x/crypto/bcrypt"
"time"
)
func main() {
password := []byte("thisIsPassWord")
nowG := time.Now()
hashedPassword, _ := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
fmt.Println("加密后", string(hashedPassword), "耗时", time.Now().Sub(nowG))
nowC := time.Now()
err := bcrypt.CompareHashAndPassword(hashedPassword, password)
fmt.Println("验证耗费时间", time.Now().Sub(nowC))
fmt.Println(err)
}
// 结果
// 加密后 $2a$10$ESkb/bwSyISLgq1bOH0C2utXdb.hcH9oBQD1hUnfDOzm4bMKK6EX2 耗时 67.9985ms
// 验证耗费时间 66.0008ms
// <nil>
将加密后的密码串存入数据表, 然后用户登录传递明文密码(也可以前段加密后端再解密成明文)进行验证
密码串解析
shell
复制代码
$2a$10$ESkb/bwSyISLgq1bOH0C2utXdb.hcH9oBQD1hUnfDOzm4bMKK6EX2
$ 为分隔符
2a bcrypt加密版本号
10 Cost值
ESkb/bwSyISLgq1bOH0C2utXdb 盐
hcH9oBQD1hUnfDOzm4bMKK6EX2 密码密文
优缺点
makefile
复制代码
优点:
单向HASH,不可解密
盐值随机(有效防止彩虹表碰撞)
破解时间成本极高
缺点:
效率较慢(相较于mad5/sha算法)
源码分析
go
复制代码
// GenerateFromPassword returns the bcrypt hash of the password at the given
// cost. If the cost given is less than MinCost, the cost will be set to
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
// to compare the returned hashed password with its cleartext version.
func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
p, err := newFromPassword(password, cost)
if err != nil {
return nil, err
}
return p.Hash(), nil
}
func newFromPassword(password []byte, cost int) (*hashed, error) {
if cost < MinCost {
cost = DefaultCost
}
p := new(hashed)
p.major = majorVersion
p.minor = minorVersion
err := checkCost(cost)
if err != nil {
return nil, err
}
p.cost = cost
unencodedSalt := make([]byte, maxSaltSize)
_, err = io.ReadFull(rand.Reader, unencodedSalt)
if err != nil {
return nil, err
}
p.salt = base64Encode(unencodedSalt)
hash, err := bcrypt(password, p.cost, p.salt)
if err != nil {
return nil, err
}
p.hash = hash
return p, err
}
// CompareHashAndPassword compares a bcrypt hashed password with its possible
// plaintext equivalent. Returns nil on success, or an error on failure.
func CompareHashAndPassword(hashedPassword, password []byte) error {
p, err := newFromHash(hashedPassword)
if err != nil {
return err
}
otherHash, err := bcrypt(password, p.cost, p.salt)
if err != nil {
return err
}
otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
return nil
}
return ErrMismatchedHashAndPassword
}
加密就是随机生成16位byte再转成base64当做salt, 用salt和cost进行加密
解密就是用已有的加密哈希的salt和cost对现有密码进行加密来确认密码密文是否一致
技术链接
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2021-11-30 (转)python logging日志模块以及多进程日志
2021-11-30 (转)Python 如何仅用5000 行代码,实现强大的 logging 模块?
2018-11-30 (转)9 db2trc案例2(1,2)
2018-11-30 (转)【学习笔记】通过netstat+rmsock查找AIX端口对应进程
2018-11-30 (转)Python: super 没那么简单
2018-11-30 (转)Python内置函数进阶之“属性(property())”详解
2018-11-30 (转)python3-staticmethod与classmethod