这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天
加密算法
我们的项目我负责的是用户注册以及用户登录的功能,因此我们存在一个需求,加密我们的用户密码,在我们使用Java的过程中,我们可以使用SpringSecurity框架来做权限控制,在SpringSecurity我们可以使用密码生成算法来生成我们用户的密码,这里使用的是加盐的密码生成规则。
但是go语言的gin框架似乎没有这个功能,所以我在github找到了一个加盐的项目,它已经实现了一个MD5加盐加密的算法,我们只需要简单的使用即可。
上面是它的github地址,项目readme介绍了两种使用方式,一种是默认配置一种是自定义配置。
package main
import (
"crypto/md5"
"fmt"
"github.com/anaskhan96/go-password-encoder"
)
func main() {
// 默认配置
salt, encodedPwd := password.Encode("generic password", nil)
check := password.Verify("generic password", salt, encodedPwd, nil)
fmt.Println(check) // true
// 自定义配置
options := &password.Options{10, 10000, 50, md5.New}
salt, encodedPwd = password.Encode("generic password", options)
check = password.Verify("generic password", salt, encodedPwd, options)
fmt.Println(check) // true
}
事情到这里很简单了,我们只需要根据样例生成密钥,但是我们如果只是把生成的加密过的密码存到数据库,我们是没法进行密码比对的,所以我们需要把盐也加到数据库,我们有个简单的方法,那就是把盐和加密的密码拼在一起,通过$来分割存到数据库即可。
func SaltEncodePwd(pwd string) string {
options := &Options{SaltLen: 6, Iterations: 10000, KeyLen: 12, HashFunction: sha512.New}
salt, pwds := Encode(pwd, options)
password := fmt.Sprintf("$%s$%s", salt, pwds)
return password
}
然后解密的时候我们只需要把前端传的密码放进去和我们数据库的密码比对(记得把盐分割出来),如此一来就可以轻松进行密码校验。
然后说一下其中遇到的坑,首先是这个自定义选项,只要数据加密和解密都是一样的就可以了,可以成功的验证。
MD5
Message Digest algorithm 5,信息摘要算法
特点 压缩性:任意长度的数据,算出的 MD5 值长度都是固定的;
容易计算:从原数据计算出 MD5 值很容易;
抗修改性:对原数据进行任何改动,哪怕只修改 1 个字节,所得到的 MD5 值都有很大区别;
强抗碰撞:想找到两个不同的数据,使它们具有相同的 MD5 值是非常困难的;
不可逆:
举一个最简单的例子:有一个作坊可以将面粉加工成面条,生意很火,有很多人都在那里加工面条,你将一袋面粉也送了过去,要求加工成面条,没过多久,作坊给你把加工好的面条拿了出来,你能判断出这个面条是用你的面粉加工的吗? 总结:由于 MD5 是一个消息摘要,它会损失原数据,所以我们不能通过最终打散的 MD5 值计算出的 MD5 值,来推断出原数据 总结 MD5 不能直接存储,容易被暴力破解,所以我们选择盐值加密
盐值加密
特点 通过生成随机数与MD5生成字符串进行组合 数据库同时存储MD5值与salt值。验证正确性时使用salt进行MD5即可