76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package passwordvalidator
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Validate returns nil if the password has greater than or
|
|
// equal to the minimum entropy. If not, an error is returned
|
|
// that explains how the password can be strengthened. This error
|
|
// is safe to show the client
|
|
func Validate(password string, minEntropy float64) error {
|
|
entropy := getEntropy(password)
|
|
if entropy >= minEntropy {
|
|
return nil
|
|
}
|
|
|
|
hasReplace := false
|
|
hasSep := false
|
|
hasOtherSpecial := false
|
|
hasLower := false
|
|
hasUpper := false
|
|
hasDigits := false
|
|
for _, c := range password {
|
|
if strings.ContainsRune(replaceChars, c) {
|
|
hasReplace = true
|
|
continue
|
|
}
|
|
if strings.ContainsRune(sepChars, c) {
|
|
hasSep = true
|
|
continue
|
|
}
|
|
if strings.ContainsRune(otherSpecialChars, c) {
|
|
hasOtherSpecial = true
|
|
continue
|
|
}
|
|
if strings.ContainsRune(lowerChars, c) {
|
|
hasLower = true
|
|
continue
|
|
}
|
|
if strings.ContainsRune(upperChars, c) {
|
|
hasUpper = true
|
|
continue
|
|
}
|
|
if strings.ContainsRune(digitsChars, c) {
|
|
hasDigits = true
|
|
continue
|
|
}
|
|
}
|
|
|
|
allMessages := []string{}
|
|
|
|
if !hasOtherSpecial || !hasSep || !hasReplace {
|
|
allMessages = append(allMessages, "including more special characters")
|
|
}
|
|
if !hasLower {
|
|
allMessages = append(allMessages, "using lowercase letters")
|
|
}
|
|
if !hasUpper {
|
|
allMessages = append(allMessages, "using uppercase letters")
|
|
}
|
|
if !hasDigits {
|
|
allMessages = append(allMessages, "using numbers")
|
|
}
|
|
|
|
if len(allMessages) > 0 {
|
|
return fmt.Errorf(
|
|
"insecure password, try %v or using a longer password",
|
|
strings.Join(allMessages, ", "),
|
|
)
|
|
}
|
|
|
|
return errors.New("insecure password, try using a longer password")
|
|
}
|