From af6d87c1a3a755d36cdd4f3913a24488ddd1f325 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Sat, 5 Aug 2023 17:54:41 +0200 Subject: [PATCH] #53 and #52: Update "Number" references to "Numeric" in password generator Replaced all instances of "Number" with "Numeric" in the password generator. This modification will make the password generation code more intuitive and readable. Moreover, minimum character requirements were added for each character type, giving more flexibility to the password generation settings. --- cmd/apg/apg.go | 20 ++++++++++++++------ config.go | 8 ++++++-- mode.go | 18 +++++++++--------- mode_test.go | 16 ++++++++-------- random_test.go | 12 ++++++------ 5 files changed, 43 insertions(+), 31 deletions(-) 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 {