security improvements

This commit is contained in:
Fran Jurmanović
2025-06-29 21:59:41 +02:00
parent 7fdda06dba
commit caba5bae70
30 changed files with 3929 additions and 147 deletions

View File

@@ -0,0 +1,82 @@
package password
import (
"errors"
"os"
"golang.org/x/crypto/bcrypt"
)
const (
// MinPasswordLength defines the minimum password length
MinPasswordLength = 8
// BcryptCost defines the cost factor for bcrypt hashing
BcryptCost = 12
)
// HashPassword hashes a plain text password using bcrypt
func HashPassword(password string) (string, error) {
if len(password) < MinPasswordLength {
return "", errors.New("password must be at least 8 characters long")
}
hashedBytes, err := bcrypt.GenerateFromPassword([]byte(password), BcryptCost)
if err != nil {
return "", err
}
return string(hashedBytes), nil
}
// VerifyPassword verifies a plain text password against a hashed password
func VerifyPassword(hashedPassword, password string) error {
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
// ValidatePasswordStrength validates password complexity requirements
func ValidatePasswordStrength(password string) error {
if len(password) < MinPasswordLength {
return errors.New("password must be at least 8 characters long")
}
if os.Getenv("ENFORCE_PASSWORD_STRENGTH") == "true" {
if len(password) < MinPasswordLength {
return errors.New("password must be at least 8 characters long")
}
hasUpper := false
hasLower := false
hasDigit := false
hasSpecial := false
for _, char := range password {
switch {
case char >= 'A' && char <= 'Z':
hasUpper = true
case char >= 'a' && char <= 'z':
hasLower = true
case char >= '0' && char <= '9':
hasDigit = true
case char >= '!' && char <= '/' || char >= ':' && char <= '@' || char >= '[' && char <= '`' || char >= '{' && char <= '~':
hasSpecial = true
}
}
if !hasUpper {
return errors.New("password must contain at least one uppercase letter")
}
if !hasLower {
return errors.New("password must contain at least one lowercase letter")
}
if !hasDigit {
return errors.New("password must contain at least one digit")
}
if !hasSpecial {
return errors.New("password must contain at least one special character")
}
return nil
}
return nil
}