概述
PBKDF2(Password-Based Key Derivation Function) 是一個用來導出密鑰的函數,常用於生成加密的密碼。原理是通過 password 和 salt 進行 hash 加密,然後將結果作爲 salt 與 password 再進行 hash,多次重複此過程,生成最終的密文。如果重複的次數足夠大(幾千數萬次),破解的成本就會變得很高。而鹽值的添加也會增加“彩虹表”攻擊的難度。
用戶密碼採用PBKDF2算法存儲,比較安全。
代碼
package pbkdf2
import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
mathrand "math/rand"
"golang.org/x/crypto/pbkdf2"
)
const (
saltMinLen = 8
saltMaxLen = 32
iter = 1000
keyLen = 32
)
// EncryptPwd 加密密碼
func EncryptPwd(pwd string) (encrypt string, err error) {
// 1、生成隨機長度的鹽值
salt, err := randSalt()
if err != nil {
return
}
// 2、生成加密串
en := encryptPwdWithSalt([]byte(pwd), salt)
en = append(en, salt...)
// 3、合併鹽值
encrypt = base64.StdEncoding.EncodeToString(en)
return
}
func randSalt() ([]byte, error) {
// 生成8-32之間的隨機數字
salt := make([]byte, mathrand.Intn(saltMaxLen-saltMinLen)+saltMinLen)
_, err := rand.Read(salt)
if err != nil {
return nil, err
}
return salt, nil
}
func encryptPwdWithSalt(pwd, salt []byte) (pwdEn []byte) {
pwd = append(pwd, salt...)
pwdEn = pbkdf2.Key(pwd, salt, iter, keyLen, sha256.New)
return
}
// CheckEncryptPwdMatch 驗證密碼是否與加密串匹配
func CheckEncryptPwdMatch(pwd, encrypt string) (ok bool) {
// 1、參數校驗
if len(encrypt) == 0 {
return
}
enDecode, err := base64.StdEncoding.DecodeString(encrypt)
if err != nil {
return
}
// 2、截取加密串 固定長度
salt := enDecode[keyLen:]
// 3、比對
enBase64 := base64.StdEncoding.EncodeToString(enDecode[0:keyLen])
pwdEnBase64 := base64.StdEncoding.EncodeToString(encryptPwdWithSalt([]byte(pwd), salt))
ok = enBase64 == pwdEnBase64
return
}
參考:
用戶密碼到底要怎麼加密存儲?