为什么要加密
人们往往有使用同一密码的习惯, 为了防止数据库意外泄露/破坏和出于保护用户隐私的目的, 不应在数据库里存入用户密码明文
实现
代码
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>
将加密后的密码串存入数据表, 然后用户登录传递明文密码(也可以前段加密后端再解密成明文)进行验证
密码串解析
$2a$10$ESkb/bwSyISLgq1bOH0C2utXdb.hcH9oBQD1hUnfDOzm4bMKK6EX2 $ 为分隔符 2a bcrypt加密版本号 10 Cost值 ESkb/bwSyISLgq1bOH0C2utXdb 盐 hcH9oBQD1hUnfDOzm4bMKK6EX2 密码密文
优缺点
优点: 单向HASH,不可解密 盐值随机(有效防止彩虹表碰撞) 破解时间成本极高 缺点: 效率较慢(相较于mad5/sha算法)
源码分析
// 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 } // 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 }
就是用已有的加密哈希的salt和cost对现有密码进行加密来确认密码密文是否一致
补充
1 最主要还是得用户的密码设置复杂一些(可以考虑强制), 最好是大小写加特殊字符, 还有就是提醒用户尽量不同网站用不同的密码 2 可以在密码里面加一些固有字段, 也能提升安全等级, 比如在前后或者在中间加参数再进行加密解密(用户不改我们帮他改)