package password import ( "regexp" "unicode" ) const ( // MinPasswordLength is the minimum required password length MinPasswordLength = 8 // MaxPasswordLength is the maximum allowed password length MaxPasswordLength = 128 ) var ( // Special characters allowed in passwords specialCharRegex = regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]`) ) // PasswordValidator provides password strength validation type PasswordValidator interface { ValidatePasswordStrength(password string) error } type passwordValidator struct{} // NewPasswordValidator creates a new password validator func NewPasswordValidator() PasswordValidator { return &passwordValidator{} } // ValidatePasswordStrength validates that a password meets strength requirements // Requirements: // - At least 8 characters long // - At most 128 characters long // - Contains at least one uppercase letter // - Contains at least one lowercase letter // - Contains at least one digit // - Contains at least one special character // // CWE-521: Returns granular error messages to help users create strong passwords func (v *passwordValidator) ValidatePasswordStrength(password string) error { // Check length first if len(password) < MinPasswordLength { return ErrPasswordTooShort } if len(password) > MaxPasswordLength { return ErrPasswordTooLong } // Check character type requirements var ( hasUpper bool hasLower bool hasNumber bool hasSpecial bool ) for _, char := range password { switch { case unicode.IsUpper(char): hasUpper = true case unicode.IsLower(char): hasLower = true case unicode.IsNumber(char): hasNumber = true } } // Check for special characters hasSpecial = specialCharRegex.MatchString(password) // Return granular error for the first missing requirement // This provides specific feedback to users about what's missing if !hasUpper { return ErrPasswordNoUppercase } if !hasLower { return ErrPasswordNoLowercase } if !hasNumber { return ErrPasswordNoNumber } if !hasSpecial { return ErrPasswordNoSpecialChar } return nil }