golang pbkdf2加密存儲用戶密碼

概述

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
}

參考:
用戶密碼到底要怎麼加密存儲?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章