go-password-encoder
密码如何存储?
密码存储也是一门重要的学问:
- 不能明文存储:一旦泄漏,将会造成巨大的损失
- 密文加密:要求密文不可反解
- 对称加密:密文可被反解-加密解密用的是同一把钥匙,如果钥匙丢了,则数据库的所有密码仍然会被全部破解
- 非对称加密:加密解密用的不是同一把钥匙,即使丢失一把钥匙,仍然不会被窃取,但是这种非对称加密也不是完全满足密文不可反解的
- md5信息摘要算法 + salt:满足密文不可反解,就算密码被盗,不光是被盗者破不了,连系统的开发者也破不了,只有用户输入正确的密码才行,这样才能最大限度的保证数据的安全
如果密码不可反解,那用户如何找回密码呢?- 早期的互联网开发是直接将原始密码直接发给用户,现在通用的做法是给客户发一个链接,让客户自己去修改密码
彩虹表
光md5加密,密码还是有被盗的风险, 详情请了解 彩虹表
对密码进行md5加密
# install
go get github.com/anaskhan96/go-password-encoder
package main
import (
"crypto/md5"
"fmt"
"github.com/anaskhan96/go-password-encoder"
)
func main() {
// Using the default options
salt, encodedPwd := password.Encode("generic password", nil)
check := password.Verify("generic password", salt, encodedPwd, nil)
fmt.Println(check) // true
// Using custom options
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
}
以上2种方法都能达到我们的目的,但实际开发中,我们会选择上面一个
package main
import (
"fmt"
"github.com/anaskhan96/go-password-encoder"
"strings"
)
func main() {
// Using the default options
//1, 对密码加密
passwordFromClient := "password from client"
salt, encodedPwd := password.Encode(passwordFromClient, nil) //用默认的option
//数据库中我们可以用password一个字段来存储我们的密码,格式 salt$encodedPwd
pwdSavedInDB := fmt.Sprintf("%s$%s", salt, encodedPwd)
//2.验证
arr := strings.Split(pwdSavedInDB, "$")
check := password.Verify(passwordFromClient, arr[0], arr[1], nil)
fmt.Println(check) // true
}