Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
|
|
@ -0,0 +1,105 @@
|
|||
package gateway
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/security/password"
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/security/securestring"
|
||||
)
|
||||
|
||||
// VerifyPasswordUseCase verifies a password against a hash
|
||||
type VerifyPasswordUseCase struct {
|
||||
passwordProvider password.PasswordProvider
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// ProvideVerifyPasswordUseCase creates a new VerifyPasswordUseCase
|
||||
func ProvideVerifyPasswordUseCase(
|
||||
passwordProvider password.PasswordProvider,
|
||||
logger *zap.Logger,
|
||||
) *VerifyPasswordUseCase {
|
||||
return &VerifyPasswordUseCase{
|
||||
passwordProvider: passwordProvider,
|
||||
logger: logger.Named("verify-password-usecase"),
|
||||
}
|
||||
}
|
||||
|
||||
// Execute verifies a plain password against a hashed password
|
||||
// Returns ErrInvalidCredentials if password doesn't match (for security)
|
||||
func (uc *VerifyPasswordUseCase) Execute(plainPassword, passwordHash string) error {
|
||||
// Create secure string from password
|
||||
securePassword, err := securestring.NewSecureString(plainPassword)
|
||||
if err != nil {
|
||||
uc.logger.Error("failed to create secure password", zap.Error(err))
|
||||
return fmt.Errorf("failed to process password: %w", err)
|
||||
}
|
||||
defer securePassword.Wipe() // Clean up password from memory
|
||||
|
||||
// Verify password
|
||||
match, err := uc.passwordProvider.ComparePasswordAndHash(securePassword, passwordHash)
|
||||
if err != nil {
|
||||
uc.logger.Error("failed to compare password and hash", zap.Error(err))
|
||||
return fmt.Errorf("failed to verify password: %w", err)
|
||||
}
|
||||
|
||||
if !match {
|
||||
uc.logger.Debug("password verification failed")
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
|
||||
uc.logger.Debug("password verified successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExecuteTimingSafe verifies a password in a timing-safe manner
|
||||
// CWE-208: Observable Timing Discrepancy - Prevents user enumeration via timing attacks
|
||||
//
|
||||
// This method ALWAYS performs password hashing, even when the user doesn't exist,
|
||||
// to ensure constant-time behavior regardless of whether the email exists in the system.
|
||||
//
|
||||
// Parameters:
|
||||
// - plainPassword: The password to verify
|
||||
// - passwordHash: The hash to compare against (empty string if user doesn't exist)
|
||||
// - userExists: Whether the user exists in the system
|
||||
//
|
||||
// Returns ErrInvalidCredentials if verification fails for any reason
|
||||
func (uc *VerifyPasswordUseCase) ExecuteTimingSafe(plainPassword, passwordHash string, userExists bool) error {
|
||||
// Create secure string from password
|
||||
securePassword, err := securestring.NewSecureString(plainPassword)
|
||||
if err != nil {
|
||||
uc.logger.Error("failed to create secure password", zap.Error(err))
|
||||
return fmt.Errorf("failed to process password: %w", err)
|
||||
}
|
||||
defer securePassword.Wipe() // Clean up password from memory
|
||||
|
||||
if !userExists || passwordHash == "" {
|
||||
// User doesn't exist or no password hash available
|
||||
// Perform dummy password hashing to maintain constant time
|
||||
uc.logger.Debug("performing timing-safe dummy password verification")
|
||||
match, err := uc.passwordProvider.ComparePasswordAndHash(securePassword, password.DummyPasswordHash)
|
||||
if err != nil {
|
||||
// Even if dummy verification fails, we don't care about the error
|
||||
// The important part is that we spent the same amount of time
|
||||
uc.logger.Debug("dummy password verification completed", zap.Error(err))
|
||||
}
|
||||
_ = match // Explicitly ignore the result
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
|
||||
// User exists - perform real password verification
|
||||
match, err := uc.passwordProvider.ComparePasswordAndHash(securePassword, passwordHash)
|
||||
if err != nil {
|
||||
uc.logger.Error("failed to compare password and hash", zap.Error(err))
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
|
||||
if !match {
|
||||
uc.logger.Debug("password verification failed")
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
|
||||
uc.logger.Debug("password verified successfully")
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue