package password import "golang.org/x/crypto/pbkdf2" import "hash" import "strconv" import "encoding/base64" import "crypto/sha1" import "crypto/sha256" import "crypto/sha512" import "crypto/rand" import "fmt" import "strings" const ( saltLength = 8 hashLength = 20 interations = 10000 hashfunc string = "sha256" ) var hashlib = map[string]func() hash.Hash{ "sha1": sha1.New, "sha256": sha256.New, "sha512": sha512.New, } // Validate a password and a hash func Validate(hash, password string) (output, replace bool) { parts := strings.Split(hash, "$") if len(parts) != 4 { return false, false } curIter, err := strconv.Atoi(parts[1]) if err != nil { return false, false } hashfuncC := strings.Split(parts[0], "_")[1] replace = (hashfuncC != hashfunc) dk := pbkdf2.Key([]byte(password), []byte(parts[2]), curIter, len(parts[3])-8, hashlib[hashfuncC]) x := fmt.Sprintf("pbkdf2_%s$%s$%s$%s", hashfuncC, parts[1], parts[2], base64.StdEncoding.EncodeToString(dk)) output = (x == hash) return } // GenerateRandomString by length for key func GenerateRandomString(n int) (string, error) { b := make([]byte, n) _, err := rand.Read(b) if err != nil { return "", err } return base64.URLEncoding.EncodeToString(b), nil } // NewHash of given password func NewHash(password string) string { salt, _ := GenerateRandomString(saltLength) dk := pbkdf2.Key([]byte(password), []byte(salt), interations, hashLength, hashlib[hashfunc]) return fmt.Sprintf("pbkdf2_%s$%d$%s$%s", hashfunc, interations, salt, base64.StdEncoding.EncodeToString(dk)) }