package pwhash import ( "crypto/pbkdf2" "crypto/rand" "crypto/sha512" "crypto/subtle" "errors" ) const defaultIter = 12504615 // from tools/finditers func HashIter(pw string, salt []byte, iter int) ([]byte, error) { return pbkdf2.Key(sha512.New, pw, salt, iter, 32) } func Hash(pw string) ([]byte, error) { buf := make([]byte, 40) salt := buf[32:] rand.Read(salt) hash, err := HashIter(pw, salt, defaultIter) if err != nil { return nil, err } copy(buf, hash) return buf, nil } var errBadPassword = errors.New("bad password") func Check(pwHash []byte, pw string) error { if len(pwHash) < 32 { return errBadPassword } wantHash, salt := pwHash[:32], pwHash[32:] gotHash, err := HashIter(pw, salt, defaultIter) if err != nil { return err } if subtle.ConstantTimeCompare(gotHash, wantHash) == 0 { return errBadPassword } return nil }