数据库在存储密码时,不能明文存储,需要加密后存储
加密算法有很多种,比如:对称加密,非对称加密,哈希算法,密码派生等
在加密之前,我们需要生成一些随机数,这些随机数称为盐
什么是盐?为什么需要盐?
盐是一种加密算法中的一种参数,它是一个随机数,用于增加破解密码的难度
把密码想象成一盘菜,盐就是调料,不加调料就是原汁原味的菜,调料加多加少,菜口味就不一样了
也就是说,盐的多少,会影响到加密后的结果,如果不使用盐,那么相同的密码,加密后的结果是一样的,这样就很容易被破解
盐的生成方式有很多种,比如:随机数,时间戳等
这里用随机数来举例:
func generateSalt(length int) []byte {
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
salt := make([]byte, length)
rand.Read(salt)
for key, val := range salt {
salt[key] = alphanum[val%byte(len(alphanum))]
}
return salt
}
生成盐之后,我们就可以对密码进行加密了
加密后的密码要使用 hex.EncodeToString
转换成字符串
salt := generateSalt(16)
encoded := pbkdf2.Key([]byte("uccs"), salt, 100, 32, sha256.New)
encodedPwd := hex.EncodeToString(encodedPwd)
因为这个加密算法是不可逆的,也就说你不能通过加密后的密码,反推出原始密码
那用户输入密码时,如何知道密码是否正确呢?
所以在存储加密后的密码时,还要存储盐和加密算法的参数
这里使用的是 pbkdf2
算法,它的参数有:原始密码,盐,迭代次数,密钥长度,哈希算法
所以最终存在数据的密码是:
pwd := fmt.Sprintf("%s$%s$%d$%d$%s", encodedPwd, salt, 100, 32, "pbkdf2-sha256")
这样在验证密码时,就可以通过这些参数,把用户输入的密码,加密后,再和数据库中存储的密码进行比较,如果相同,就说明密码正确