diff --git a/cmd/apg/apg.go b/cmd/apg/apg.go index f5fc1f5..2e5b0ba 100644 --- a/cmd/apg/apg.go +++ b/cmd/apg/apg.go @@ -18,9 +18,13 @@ func main() { var ms string var co, hr, lc, nu, sp, uc bool flag.BoolVar(&lc, "L", false, "") + flag.Int64Var(&c.MinLowerCase, "mL", c.MinLowerCase, "") flag.BoolVar(&uc, "U", false, "") + flag.Int64Var(&c.MinUpperCase, "mU", c.MinUpperCase, "") flag.BoolVar(&nu, "N", false, "") + flag.Int64Var(&c.MinNumeric, "mN", c.MinNumeric, "") flag.BoolVar(&sp, "S", false, "") + flag.Int64Var(&c.MinSpecial, "mS", c.MinSpecial, "") flag.BoolVar(&co, "C", false, "") flag.BoolVar(&hr, "H", false, "") flag.Int64Var(&c.FixedLength, "f", 0, "") @@ -42,13 +46,13 @@ func main() { c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeUpperCase) } if nu { - c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeNumber) + c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeNumeric) } if sp { c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeSpecial) } if co { - c.Mode = apg.MaskSetMode(c.Mode, apg.ModeLowerCase|apg.ModeNumber| + c.Mode = apg.MaskSetMode(c.Mode, apg.ModeLowerCase|apg.ModeNumeric| apg.ModeSpecial|apg.ModeUpperCase) c.Mode = apg.MaskClearMode(c.Mode, apg.ModeHumanReadable) } @@ -91,12 +95,16 @@ Flags: -E CHARS List of characters to be excluded in the generated password -M [LUNSHClunshc] New style password flags - Note: new-style flags have higher priority than any of the old-style flags - -L Toggle lower case characters in passwords (Default: on) - -U Toggle upper case characters in passwords (Default: on) + -mL NUMBER Minimal amount of lower-case characters (implies -L) + -mN NUMBER Minimal amount of numeric characters (imlies -N) + -mS NUMBER Minimal amount of special characters (imlies -S) + -mU NUMBER Minimal amount of upper-case characters (imlies -U) + -C Enable complex password mode (implies -L -U -N -S and disables -H) + -H Avoid ambiguous characters in passwords (i. e.: 1, l, I, O, 0) (Default: off) + -L Toggle lower-case characters in passwords (Default: on) -N Toggle numeric characters in passwords (Default: on) -S Toggle special characters in passwords (Default: off) - -H Avoid ambiguous characters in passwords (i. e.: 1, l, I, O, 0) (Default: off) - -C Enable complex password mode (implies -L -U -N -S and disables -H) + -U Toggle upper-case characters in passwords (Default: on) - Note: this flag has higher priority than the other old-style flags -l Spell generated passwords in phonetic alphabet (Default: off) -p Check the HIBP database if the generated passwords was found in a leak before (Default: off) diff --git a/config.go b/config.go index ef2378c..6358a34 100644 --- a/config.go +++ b/config.go @@ -8,7 +8,7 @@ const ( DefaultMaxLength int64 = 20 // DefaultMode sets the default character set mode bitmask to a combination of // lower- and upper-case characters as well as numbers - DefaultMode ModeMask = ModeLowerCase | ModeNumber | ModeUpperCase + DefaultMode ModeMask = ModeLowerCase | ModeNumeric | ModeUpperCase // DefaultNumberPass reflects the default amount of passwords returned by the generator DefaultNumberPass int64 = 6 ) @@ -23,7 +23,11 @@ type Config struct { // MaxLength sets the maximum length for a generated password MaxLength int64 // MinLength sets the minimum length for a generated password - MinLength int64 + MinLength int64 + MinLowerCase int64 + MinNumeric int64 + MinSpecial int64 + MinUpperCase int64 // Mode holds the different character modes for the Random algorithm Mode ModeMask // NumberPass sets the number of passwords that are generated diff --git a/mode.go b/mode.go index 595906c..3595114 100644 --- a/mode.go +++ b/mode.go @@ -11,8 +11,8 @@ type Mode uint8 type ModeMask uint8 const ( - // ModeNumber sets the bitmask to include numbers in the generated passwords - ModeNumber = 1 << iota + // ModeNumeric sets the bitmask to include numeric in the generated passwords + ModeNumeric = 1 << iota // ModeLowerCase sets the bitmask to include lower case characters in the // generated passwords ModeLowerCase @@ -35,8 +35,8 @@ const ( CharRangeAlphaUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // CharRangeAlphaUpperHuman represents the human-readable upper-case alphabetical characters CharRangeAlphaUpperHuman = "ABCDEFGHJKMNPQRSTUVWXYZ" - // CharRangeNumber represents all numerical characters - CharRangeNumber = "1234567890" + // CharRangeNumeric represents all numerical characters + CharRangeNumeric = "1234567890" // CharRangeNumberHuman represents all human-readable numerical characters CharRangeNumberHuman = "23456789" // CharRangeSpecial represents all special characters @@ -63,7 +63,7 @@ func ModesFromFlags(ms string) ModeMask { for _, m := range cl { switch m { case "C": - mm = MaskSetMode(mm, ModeLowerCase|ModeNumber|ModeSpecial|ModeUpperCase) + mm = MaskSetMode(mm, ModeLowerCase|ModeNumeric|ModeSpecial|ModeUpperCase) case "h": mm = MaskClearMode(mm, ModeHumanReadable) case "H": @@ -73,9 +73,9 @@ func ModesFromFlags(ms string) ModeMask { case "L": mm = MaskSetMode(mm, ModeLowerCase) case "n": - mm = MaskClearMode(mm, ModeNumber) + mm = MaskClearMode(mm, ModeNumeric) case "N": - mm = MaskSetMode(mm, ModeNumber) + mm = MaskSetMode(mm, ModeNumeric) case "s": mm = MaskClearMode(mm, ModeSpecial) case "S": @@ -98,8 +98,8 @@ func (m Mode) String() string { return "Human-readable" case ModeLowerCase: return "Lower-case" - case ModeNumber: - return "Number" + case ModeNumeric: + return "Numeric" case ModeSpecial: return "Special" case ModeUpperCase: diff --git a/mode_test.go b/mode_test.go index 7eae4a1..bf2175f 100644 --- a/mode_test.go +++ b/mode_test.go @@ -11,7 +11,7 @@ func TestSetClearHasToggleMode(t *testing.T) { }{ {"ModeHumanReadable", ModeHumanReadable}, {"ModeLowerCase", ModeLowerCase}, - {"ModeNumber", ModeNumber}, + {"ModeNumeric", ModeNumeric}, {"ModeSpecial", ModeSpecial}, {"ModeUpperCase", ModeUpperCase}, } @@ -45,24 +45,24 @@ func TestModesFromFlags(t *testing.T) { ms string mode []Mode }{ - {"ModeComplex", "C", []Mode{ModeLowerCase, ModeNumber, ModeSpecial, + {"ModeComplex", "C", []Mode{ModeLowerCase, ModeNumeric, ModeSpecial, ModeUpperCase}}, {"ModeHumanReadable", "H", []Mode{ModeHumanReadable}}, {"ModeLowerCase", "L", []Mode{ModeLowerCase}}, - {"ModeNumber", "N", []Mode{ModeNumber}}, + {"ModeNumeric", "N", []Mode{ModeNumeric}}, {"ModeUpperCase", "U", []Mode{ModeUpperCase}}, {"ModeSpecial", "S", []Mode{ModeSpecial}}, {"ModeLowerSpecialUpper", "LSUH", []Mode{ModeHumanReadable, ModeLowerCase, ModeSpecial, ModeUpperCase}}, {"ModeComplexNoHumanReadable", "Ch", []Mode{ModeLowerCase, - ModeNumber, ModeSpecial, ModeUpperCase}}, - {"ModeComplexNoLower", "Cl", []Mode{ModeNumber, ModeSpecial, + ModeNumeric, ModeSpecial, ModeUpperCase}}, + {"ModeComplexNoLower", "Cl", []Mode{ModeNumeric, ModeSpecial, ModeUpperCase}}, {"ModeComplexNoNumber", "Cn", []Mode{ModeLowerCase, ModeSpecial, ModeUpperCase}}, - {"ModeComplexNoSpecial", "Cs", []Mode{ModeLowerCase, ModeNumber, + {"ModeComplexNoSpecial", "Cs", []Mode{ModeLowerCase, ModeNumeric, ModeUpperCase}}, - {"ModeComplexNoUpper", "Cu", []Mode{ModeLowerCase, ModeNumber, + {"ModeComplexNoUpper", "Cu", []Mode{ModeLowerCase, ModeNumeric, ModeSpecial}}, } for _, tc := range tt { @@ -87,7 +87,7 @@ func TestMode_String(t *testing.T) { }{ {"ModeHumanReadable", ModeHumanReadable, "Human-readable"}, {"ModeLowerCase", ModeLowerCase, "Lower-case"}, - {"ModeNumber", ModeNumber, "Number"}, + {"ModeNumeric", ModeNumeric, "Number"}, {"ModeSpecial", ModeSpecial, "Special"}, {"ModeUpperCase", ModeUpperCase, "Upper-case"}, {"ModeUnknown", 255, "Unknown"}, diff --git a/random_test.go b/random_test.go index f7d0bca..e352319 100644 --- a/random_test.go +++ b/random_test.go @@ -112,23 +112,23 @@ func TestGenerator_RandomString(t *testing.T) { }{ { "CharRange:AlphaLower", CharRangeAlphaLower, - CharRangeAlphaUpper + CharRangeNumber + CharRangeSpecial, false, + CharRangeAlphaUpper + CharRangeNumeric + CharRangeSpecial, false, }, { "CharRange:AlphaUpper", CharRangeAlphaUpper, - CharRangeAlphaLower + CharRangeNumber + CharRangeSpecial, false, + CharRangeAlphaLower + CharRangeNumeric + CharRangeSpecial, false, }, { - "CharRange:Number", CharRangeNumber, + "CharRange:Number", CharRangeNumeric, CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeSpecial, false, }, { "CharRange:Special", CharRangeSpecial, - CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumber, false, + CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumeric, false, }, { "CharRange:Invalid", "", - CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumber + CharRangeSpecial, true, + CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumeric + CharRangeSpecial, true, }, } for _, tc := range tt { @@ -171,7 +171,7 @@ func BenchmarkGenerator_RandomBytes(b *testing.B) { func BenchmarkGenerator_RandomString(b *testing.B) { b.ReportAllocs() g := New(NewConfig()) - cr := CharRangeAlphaUpper + CharRangeAlphaLower + CharRangeNumber + CharRangeSpecial + cr := CharRangeAlphaUpper + CharRangeAlphaLower + CharRangeNumeric + CharRangeSpecial for i := 0; i < b.N; i++ { _, err := g.RandomStringFromCharRange(32, cr) if err != nil {