#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.
This commit is contained in:
Winni Neessen 2023-08-05 17:54:41 +02:00
parent d28b0645fd
commit af6d87c1a3
Signed by: wneessen
GPG key ID: 5F3AF39B820C119D
5 changed files with 43 additions and 31 deletions

View file

@ -18,9 +18,13 @@ func main() {
var ms string var ms string
var co, hr, lc, nu, sp, uc bool var co, hr, lc, nu, sp, uc bool
flag.BoolVar(&lc, "L", false, "") flag.BoolVar(&lc, "L", false, "")
flag.Int64Var(&c.MinLowerCase, "mL", c.MinLowerCase, "")
flag.BoolVar(&uc, "U", false, "") flag.BoolVar(&uc, "U", false, "")
flag.Int64Var(&c.MinUpperCase, "mU", c.MinUpperCase, "")
flag.BoolVar(&nu, "N", false, "") flag.BoolVar(&nu, "N", false, "")
flag.Int64Var(&c.MinNumeric, "mN", c.MinNumeric, "")
flag.BoolVar(&sp, "S", false, "") flag.BoolVar(&sp, "S", false, "")
flag.Int64Var(&c.MinSpecial, "mS", c.MinSpecial, "")
flag.BoolVar(&co, "C", false, "") flag.BoolVar(&co, "C", false, "")
flag.BoolVar(&hr, "H", false, "") flag.BoolVar(&hr, "H", false, "")
flag.Int64Var(&c.FixedLength, "f", 0, "") flag.Int64Var(&c.FixedLength, "f", 0, "")
@ -42,13 +46,13 @@ func main() {
c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeUpperCase) c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeUpperCase)
} }
if nu { if nu {
c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeNumber) c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeNumeric)
} }
if sp { if sp {
c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeSpecial) c.Mode = apg.MaskToggleMode(c.Mode, apg.ModeSpecial)
} }
if co { 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) apg.ModeSpecial|apg.ModeUpperCase)
c.Mode = apg.MaskClearMode(c.Mode, apg.ModeHumanReadable) 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 -E CHARS List of characters to be excluded in the generated password
-M [LUNSHClunshc] New style password flags -M [LUNSHClunshc] New style password flags
- Note: new-style flags have higher priority than any of the old-style flags - Note: new-style flags have higher priority than any of the old-style flags
-L Toggle lower case characters in passwords (Default: on) -mL NUMBER Minimal amount of lower-case characters (implies -L)
-U Toggle upper case characters in passwords (Default: on) -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) -N Toggle numeric characters in passwords (Default: on)
-S Toggle special characters in passwords (Default: off) -S Toggle special characters in passwords (Default: off)
-H Avoid ambiguous characters in passwords (i. e.: 1, l, I, O, 0) (Default: off) -U Toggle upper-case characters in passwords (Default: on)
-C Enable complex password mode (implies -L -U -N -S and disables -H)
- Note: this flag has higher priority than the other old-style flags - Note: this flag has higher priority than the other old-style flags
-l Spell generated passwords in phonetic alphabet (Default: off) -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) -p Check the HIBP database if the generated passwords was found in a leak before (Default: off)

View file

@ -8,7 +8,7 @@ const (
DefaultMaxLength int64 = 20 DefaultMaxLength int64 = 20
// DefaultMode sets the default character set mode bitmask to a combination of // DefaultMode sets the default character set mode bitmask to a combination of
// lower- and upper-case characters as well as numbers // 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 reflects the default amount of passwords returned by the generator
DefaultNumberPass int64 = 6 DefaultNumberPass int64 = 6
) )
@ -24,6 +24,10 @@ type Config struct {
MaxLength int64 MaxLength int64
// MinLength sets the minimum length for a generated password // 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 holds the different character modes for the Random algorithm
Mode ModeMask Mode ModeMask
// NumberPass sets the number of passwords that are generated // NumberPass sets the number of passwords that are generated

18
mode.go
View file

@ -11,8 +11,8 @@ type Mode uint8
type ModeMask uint8 type ModeMask uint8
const ( const (
// ModeNumber sets the bitmask to include numbers in the generated passwords // ModeNumeric sets the bitmask to include numeric in the generated passwords
ModeNumber = 1 << iota ModeNumeric = 1 << iota
// ModeLowerCase sets the bitmask to include lower case characters in the // ModeLowerCase sets the bitmask to include lower case characters in the
// generated passwords // generated passwords
ModeLowerCase ModeLowerCase
@ -35,8 +35,8 @@ const (
CharRangeAlphaUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" CharRangeAlphaUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// CharRangeAlphaUpperHuman represents the human-readable upper-case alphabetical characters // CharRangeAlphaUpperHuman represents the human-readable upper-case alphabetical characters
CharRangeAlphaUpperHuman = "ABCDEFGHJKMNPQRSTUVWXYZ" CharRangeAlphaUpperHuman = "ABCDEFGHJKMNPQRSTUVWXYZ"
// CharRangeNumber represents all numerical characters // CharRangeNumeric represents all numerical characters
CharRangeNumber = "1234567890" CharRangeNumeric = "1234567890"
// CharRangeNumberHuman represents all human-readable numerical characters // CharRangeNumberHuman represents all human-readable numerical characters
CharRangeNumberHuman = "23456789" CharRangeNumberHuman = "23456789"
// CharRangeSpecial represents all special characters // CharRangeSpecial represents all special characters
@ -63,7 +63,7 @@ func ModesFromFlags(ms string) ModeMask {
for _, m := range cl { for _, m := range cl {
switch m { switch m {
case "C": case "C":
mm = MaskSetMode(mm, ModeLowerCase|ModeNumber|ModeSpecial|ModeUpperCase) mm = MaskSetMode(mm, ModeLowerCase|ModeNumeric|ModeSpecial|ModeUpperCase)
case "h": case "h":
mm = MaskClearMode(mm, ModeHumanReadable) mm = MaskClearMode(mm, ModeHumanReadable)
case "H": case "H":
@ -73,9 +73,9 @@ func ModesFromFlags(ms string) ModeMask {
case "L": case "L":
mm = MaskSetMode(mm, ModeLowerCase) mm = MaskSetMode(mm, ModeLowerCase)
case "n": case "n":
mm = MaskClearMode(mm, ModeNumber) mm = MaskClearMode(mm, ModeNumeric)
case "N": case "N":
mm = MaskSetMode(mm, ModeNumber) mm = MaskSetMode(mm, ModeNumeric)
case "s": case "s":
mm = MaskClearMode(mm, ModeSpecial) mm = MaskClearMode(mm, ModeSpecial)
case "S": case "S":
@ -98,8 +98,8 @@ func (m Mode) String() string {
return "Human-readable" return "Human-readable"
case ModeLowerCase: case ModeLowerCase:
return "Lower-case" return "Lower-case"
case ModeNumber: case ModeNumeric:
return "Number" return "Numeric"
case ModeSpecial: case ModeSpecial:
return "Special" return "Special"
case ModeUpperCase: case ModeUpperCase:

View file

@ -11,7 +11,7 @@ func TestSetClearHasToggleMode(t *testing.T) {
}{ }{
{"ModeHumanReadable", ModeHumanReadable}, {"ModeHumanReadable", ModeHumanReadable},
{"ModeLowerCase", ModeLowerCase}, {"ModeLowerCase", ModeLowerCase},
{"ModeNumber", ModeNumber}, {"ModeNumeric", ModeNumeric},
{"ModeSpecial", ModeSpecial}, {"ModeSpecial", ModeSpecial},
{"ModeUpperCase", ModeUpperCase}, {"ModeUpperCase", ModeUpperCase},
} }
@ -45,24 +45,24 @@ func TestModesFromFlags(t *testing.T) {
ms string ms string
mode []Mode mode []Mode
}{ }{
{"ModeComplex", "C", []Mode{ModeLowerCase, ModeNumber, ModeSpecial, {"ModeComplex", "C", []Mode{ModeLowerCase, ModeNumeric, ModeSpecial,
ModeUpperCase}}, ModeUpperCase}},
{"ModeHumanReadable", "H", []Mode{ModeHumanReadable}}, {"ModeHumanReadable", "H", []Mode{ModeHumanReadable}},
{"ModeLowerCase", "L", []Mode{ModeLowerCase}}, {"ModeLowerCase", "L", []Mode{ModeLowerCase}},
{"ModeNumber", "N", []Mode{ModeNumber}}, {"ModeNumeric", "N", []Mode{ModeNumeric}},
{"ModeUpperCase", "U", []Mode{ModeUpperCase}}, {"ModeUpperCase", "U", []Mode{ModeUpperCase}},
{"ModeSpecial", "S", []Mode{ModeSpecial}}, {"ModeSpecial", "S", []Mode{ModeSpecial}},
{"ModeLowerSpecialUpper", "LSUH", []Mode{ModeHumanReadable, {"ModeLowerSpecialUpper", "LSUH", []Mode{ModeHumanReadable,
ModeLowerCase, ModeSpecial, ModeUpperCase}}, ModeLowerCase, ModeSpecial, ModeUpperCase}},
{"ModeComplexNoHumanReadable", "Ch", []Mode{ModeLowerCase, {"ModeComplexNoHumanReadable", "Ch", []Mode{ModeLowerCase,
ModeNumber, ModeSpecial, ModeUpperCase}}, ModeNumeric, ModeSpecial, ModeUpperCase}},
{"ModeComplexNoLower", "Cl", []Mode{ModeNumber, ModeSpecial, {"ModeComplexNoLower", "Cl", []Mode{ModeNumeric, ModeSpecial,
ModeUpperCase}}, ModeUpperCase}},
{"ModeComplexNoNumber", "Cn", []Mode{ModeLowerCase, ModeSpecial, {"ModeComplexNoNumber", "Cn", []Mode{ModeLowerCase, ModeSpecial,
ModeUpperCase}}, ModeUpperCase}},
{"ModeComplexNoSpecial", "Cs", []Mode{ModeLowerCase, ModeNumber, {"ModeComplexNoSpecial", "Cs", []Mode{ModeLowerCase, ModeNumeric,
ModeUpperCase}}, ModeUpperCase}},
{"ModeComplexNoUpper", "Cu", []Mode{ModeLowerCase, ModeNumber, {"ModeComplexNoUpper", "Cu", []Mode{ModeLowerCase, ModeNumeric,
ModeSpecial}}, ModeSpecial}},
} }
for _, tc := range tt { for _, tc := range tt {
@ -87,7 +87,7 @@ func TestMode_String(t *testing.T) {
}{ }{
{"ModeHumanReadable", ModeHumanReadable, "Human-readable"}, {"ModeHumanReadable", ModeHumanReadable, "Human-readable"},
{"ModeLowerCase", ModeLowerCase, "Lower-case"}, {"ModeLowerCase", ModeLowerCase, "Lower-case"},
{"ModeNumber", ModeNumber, "Number"}, {"ModeNumeric", ModeNumeric, "Number"},
{"ModeSpecial", ModeSpecial, "Special"}, {"ModeSpecial", ModeSpecial, "Special"},
{"ModeUpperCase", ModeUpperCase, "Upper-case"}, {"ModeUpperCase", ModeUpperCase, "Upper-case"},
{"ModeUnknown", 255, "Unknown"}, {"ModeUnknown", 255, "Unknown"},

View file

@ -112,23 +112,23 @@ func TestGenerator_RandomString(t *testing.T) {
}{ }{
{ {
"CharRange:AlphaLower", CharRangeAlphaLower, "CharRange:AlphaLower", CharRangeAlphaLower,
CharRangeAlphaUpper + CharRangeNumber + CharRangeSpecial, false, CharRangeAlphaUpper + CharRangeNumeric + CharRangeSpecial, false,
}, },
{ {
"CharRange:AlphaUpper", CharRangeAlphaUpper, "CharRange:AlphaUpper", CharRangeAlphaUpper,
CharRangeAlphaLower + CharRangeNumber + CharRangeSpecial, false, CharRangeAlphaLower + CharRangeNumeric + CharRangeSpecial, false,
}, },
{ {
"CharRange:Number", CharRangeNumber, "CharRange:Number", CharRangeNumeric,
CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeSpecial, false, CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeSpecial, false,
}, },
{ {
"CharRange:Special", CharRangeSpecial, "CharRange:Special", CharRangeSpecial,
CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumber, false, CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumeric, false,
}, },
{ {
"CharRange:Invalid", "", "CharRange:Invalid", "",
CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumber + CharRangeSpecial, true, CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumeric + CharRangeSpecial, true,
}, },
} }
for _, tc := range tt { for _, tc := range tt {
@ -171,7 +171,7 @@ func BenchmarkGenerator_RandomBytes(b *testing.B) {
func BenchmarkGenerator_RandomString(b *testing.B) { func BenchmarkGenerator_RandomString(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
g := New(NewConfig()) g := New(NewConfig())
cr := CharRangeAlphaUpper + CharRangeAlphaLower + CharRangeNumber + CharRangeSpecial cr := CharRangeAlphaUpper + CharRangeAlphaLower + CharRangeNumeric + CharRangeSpecial
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err := g.RandomStringFromCharRange(32, cr) _, err := g.RandomStringFromCharRange(32, cr)
if err != nil { if err != nil {