package passwordutil import ( "crypto/rand" "crypto/sha256" "encoding/hex" "errors" "strings" ) const ( saltBytes = 16 separator = "$" hashLength = 64 // sha256 hex length ) // Hash 生成 salt+hash 的存储串,格式:salt$hash(均为 hex) func Hash(plain string) (string, error) { plain = strings.TrimSpace(plain) if plain == "" { return "", errors.New("password 不能为空") } salt := make([]byte, saltBytes) if _, err := rand.Read(salt); err != nil { return "", err } saltHex := hex.EncodeToString(salt) hashHex := hashHex(saltHex, plain) return saltHex + separator + hashHex, nil } // Verify 校验存储串(salt$hash)是否匹配输入明文密码。 func Verify(stored, plain string) bool { stored = strings.TrimSpace(stored) plain = strings.TrimSpace(plain) if stored == "" || plain == "" { return false } parts := strings.Split(stored, separator) if len(parts) != 2 { return false } saltHex := strings.TrimSpace(parts[0]) hashHexStored := strings.TrimSpace(parts[1]) if saltHex == "" || len(hashHexStored) != hashLength { return false } return hashHex(saltHex, plain) == strings.ToLower(hashHexStored) } func hashHex(saltHex, plain string) string { sum := sha256.Sum256([]byte(saltHex + plain)) return hex.EncodeToString(sum[:]) }