validate.go (1675B)
1 package passwordvalidator 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 ) 8 9 // Validate returns nil if the password has greater than or 10 // equal to the minimum entropy. If not, an error is returned 11 // that explains how the password can be strengthened. This error 12 // is safe to show the client 13 func Validate(password string, minEntropy float64) error { 14 entropy := getEntropy(password) 15 if entropy >= minEntropy { 16 return nil 17 } 18 19 hasReplace := false 20 hasSep := false 21 hasOtherSpecial := false 22 hasLower := false 23 hasUpper := false 24 hasDigits := false 25 for _, c := range password { 26 if strings.ContainsRune(replaceChars, c) { 27 hasReplace = true 28 continue 29 } 30 if strings.ContainsRune(sepChars, c) { 31 hasSep = true 32 continue 33 } 34 if strings.ContainsRune(otherSpecialChars, c) { 35 hasOtherSpecial = true 36 continue 37 } 38 if strings.ContainsRune(lowerChars, c) { 39 hasLower = true 40 continue 41 } 42 if strings.ContainsRune(upperChars, c) { 43 hasUpper = true 44 continue 45 } 46 if strings.ContainsRune(digitsChars, c) { 47 hasDigits = true 48 continue 49 } 50 } 51 52 allMessages := []string{} 53 54 if !hasOtherSpecial || !hasSep || !hasReplace { 55 allMessages = append(allMessages, "including more special characters") 56 } 57 if !hasLower { 58 allMessages = append(allMessages, "using lowercase letters") 59 } 60 if !hasUpper { 61 allMessages = append(allMessages, "using uppercase letters") 62 } 63 if !hasDigits { 64 allMessages = append(allMessages, "using numbers") 65 } 66 67 if len(allMessages) > 0 { 68 return fmt.Errorf( 69 "insecure password, try %v or using a longer password", 70 strings.Join(allMessages, ", "), 71 ) 72 } 73 74 return errors.New("insecure password, try using a longer password") 75 }