Update min character options and remove HIBP check

We've added new configuration options for setting minimum counts of lowercase, numeric, special, and uppercase characters in passwords. The HIBP check feature has also been removed due to redundancy. Note: High values for these character minimums may lead to long calculation times.
This commit is contained in:
Winni Neessen 2024-03-13 21:23:56 +01:00
parent d6cfc79cf2
commit 83e910bdda
Signed by: wneessen
GPG key ID: 5F3AF39B820C119D
3 changed files with 115 additions and 34 deletions

View file

@ -88,13 +88,6 @@ func WithAlgorithm(algo Algorithm) Option {
} }
} }
// WithCheckHIBP enables the HIBP check for newly generated passwords
func WithCheckHIBP() Option {
return func(config *Config) {
config.CheckHIBP = true
}
}
// WithExcludeChars sets a list of characters to be excluded in the generated // WithExcludeChars sets a list of characters to be excluded in the generated
// passwords // passwords
func WithExcludeChars(chars string) Option { func WithExcludeChars(chars string) Option {
@ -117,6 +110,50 @@ func WithMinLength(length int64) Option {
} }
} }
// WithMinLowercase sets the minimum amount of lowercase characters that
// the generated password should contain
//
// CAVEAT: using to high values with this option, can lead to extraordinary
// calculation times, resulting in apg-go to never finish
func WithMinLowercase(amount int64) Option {
return func(config *Config) {
config.MinLowerCase = amount
}
}
// WithMinNumeric sets the minimum amount of numeric characters that
// the generated password should contain
//
// CAVEAT: using to high values with this option, can lead to extraordinary
// calculation times, resulting in apg-go to never finish
func WithMinNumeric(amount int64) Option {
return func(config *Config) {
config.MinNumeric = amount
}
}
// WithMinSpecial sets the minimum amount of special characters that
// the generated password should contain
//
// CAVEAT: using to high values with this option, can lead to extraordinary
// calculation times, resulting in apg-go to never finish
func WithMinSpecial(amount int64) Option {
return func(config *Config) {
config.MinSpecial = amount
}
}
// WithMinUppercase sets the minimum amount of uppercase characters that
// the generated password should contain
//
// CAVEAT: using to high values with this option, can lead to extraordinary
// calculation times, resulting in apg-go to never finish
func WithMinUppercase(amount int64) Option {
return func(config *Config) {
config.MinUpperCase = amount
}
}
// WithMaxLength overrides the maximum password length // WithMaxLength overrides the maximum password length
func WithMaxLength(length int64) Option { func WithMaxLength(length int64) Option {
return func(config *Config) { return func(config *Config) {
@ -124,9 +161,9 @@ func WithMaxLength(length int64) Option {
} }
} }
// WithNumberPass overrides the amount of generated passwords setting // WithModeMask overrides the default mode mask for the random algorithm
func WithNumberPass(amount int64) Option { func WithModeMask(mask ModeMask) Option {
return func(config *Config) { return func(config *Config) {
config.NumberPass = amount config.Mode = mask
} }
} }

View file

@ -31,6 +31,10 @@ func TestNewConfig(t *testing.T) {
t.Errorf("NewConfig() failed, expected number of passwords: %d, got: %d", t.Errorf("NewConfig() failed, expected number of passwords: %d, got: %d",
DefaultNumberPass, c.NumberPass) DefaultNumberPass, c.NumberPass)
} }
if c.Mode != DefaultMode {
t.Errorf("NewConfig() failed, expected mode mask: %d, got: %d",
DefaultMode, c.Mode)
}
} }
func TestWithAlgorithm(t *testing.T) { func TestWithAlgorithm(t *testing.T) {
@ -39,7 +43,7 @@ func TestWithAlgorithm(t *testing.T) {
algo Algorithm algo Algorithm
want int want int
}{ }{
{"Pronouncble passwords", AlgoPronounceable, 0}, {"Pronounceable passwords", AlgoPronounceable, 0},
{"Random passwords", AlgoRandom, 1}, {"Random passwords", AlgoRandom, 1},
{"Coinflip", AlgoCoinFlip, 2}, {"Coinflip", AlgoCoinFlip, 2},
{"Unsupported", AlgoUnsupported, 3}, {"Unsupported", AlgoUnsupported, 3},
@ -63,18 +67,6 @@ func TestWithAlgorithm(t *testing.T) {
} }
} }
func TestWithCheckHIBP(t *testing.T) {
c := NewConfig(WithCheckHIBP())
if c == nil {
t.Errorf("NewConfig(WithCheckHIBP()) failed, expected config pointer but got nil")
return
}
if c.CheckHIBP != true {
t.Errorf("NewConfig(WithCheckHIBP()) failed, expected min length: %t, got: %t",
true, c.CheckHIBP)
}
}
func TestWithExcludeChars(t *testing.T) { func TestWithExcludeChars(t *testing.T) {
e := "abcdefg" e := "abcdefg"
c := NewConfig(WithExcludeChars(e)) c := NewConfig(WithExcludeChars(e))
@ -83,7 +75,7 @@ func TestWithExcludeChars(t *testing.T) {
return return
} }
if c.ExcludeChars != e { if c.ExcludeChars != e {
t.Errorf("NewConfig(WithExcludeChars()) failed, expected min length: %s, got: %s", t.Errorf("NewConfig(WithExcludeChars()) failed, expected chars: %s, got: %s",
e, c.ExcludeChars) e, c.ExcludeChars)
} }
} }
@ -96,7 +88,7 @@ func TestWithFixedLength(t *testing.T) {
return return
} }
if c.FixedLength != e { if c.FixedLength != e {
t.Errorf("NewConfig(WithFixedLength()) failed, expected min length: %d, got: %d", t.Errorf("NewConfig(WithFixedLength()) failed, expected fixed length: %d, got: %d",
e, c.FixedLength) e, c.FixedLength)
} }
} }
@ -127,15 +119,67 @@ func TestWithMinLength(t *testing.T) {
} }
} }
func TestWithNumberPass(t *testing.T) { func TestWithMinLowercase(t *testing.T) {
var e int64 = 123 var e int64 = 2
c := NewConfig(WithNumberPass(e)) c := NewConfig(WithMinLowercase(e))
if c == nil { if c == nil {
t.Errorf("NewConfig(WithNumberPass()) failed, expected config pointer but got nil") t.Errorf("NewConfig(WithMinLowercase()) failed, expected config pointer but got nil")
return return
} }
if c.NumberPass != e { if c.MinLowerCase != e {
t.Errorf("NewConfig(WithNumberPass()) failed, expected number of passwords: %d, got: %d", t.Errorf("NewConfig(WithMinLowercase()) failed, expected min amount: %d, got: %d",
e, c.NumberPass) e, c.MinLowerCase)
}
}
func TestWithMinNumeric(t *testing.T) {
var e int64 = 3
c := NewConfig(WithMinNumeric(e))
if c == nil {
t.Errorf("NewConfig(WithMinNumeric()) failed, expected config pointer but got nil")
return
}
if c.MinNumeric != e {
t.Errorf("NewConfig(WithMinNumeric()) failed, expected min amount: %d, got: %d",
e, c.MinNumeric)
}
}
func TestWithMinSpecial(t *testing.T) {
var e int64 = 4
c := NewConfig(WithMinSpecial(e))
if c == nil {
t.Errorf("NewConfig(WithMinSpecial()) failed, expected config pointer but got nil")
return
}
if c.MinSpecial != e {
t.Errorf("NewConfig(WithMinSpecial()) failed, expected min amount: %d, got: %d",
e, c.MinSpecial)
}
}
func TestWithMinUppercase(t *testing.T) {
var e int64 = 5
c := NewConfig(WithMinUppercase(e))
if c == nil {
t.Errorf("NewConfig(WithMinUppercase()) failed, expected config pointer but got nil")
return
}
if c.MinUpperCase != e {
t.Errorf("NewConfig(WithMinUppercase()) failed, expected min amount: %d, got: %d",
e, c.MinUpperCase)
}
}
func TestWithModeMask(t *testing.T) {
e := DefaultMode
c := NewConfig(WithModeMask(e))
if c == nil {
t.Errorf("NewConfig(WithModeMask()) failed, expected config pointer but got nil")
return
}
if c.Mode != e {
t.Errorf("NewConfig(WithModeMask()) failed, expected mask: %d, got: %d",
e, c.Mode)
} }
} }

View file

@ -416,8 +416,8 @@ func TestCheckMinimumRequirements(t *testing.T) {
} }
func TestGenerateRandom(t *testing.T) { func TestGenerateRandom(t *testing.T) {
config := NewConfig(WithAlgorithm(AlgoRandom), WithNumberPass(1), config := NewConfig(WithAlgorithm(AlgoRandom), WithMinLength(1),
WithMinLength(1), WithMaxLength(1)) WithMaxLength(1))
config.MinNumeric = 1 config.MinNumeric = 1
generator := New(config) generator := New(config)
pw, err := generator.generateRandom() pw, err := generator.generateRandom()