From 77d5271b5a2229dac9f039d2be1b35bcc72ca837 Mon Sep 17 00:00:00 2001 From: brent s Date: Thu, 3 Mar 2022 05:51:22 -0500 Subject: [PATCH] before adding cryptoshuffler --- cmd/pwgen/args.go | 25 ++++++++++++----------- cmd/pwgen/main.go | 21 +++++++++++++++++-- pwgenerator/funcs.go | 35 +++++++++++++++++++++++++++++--- pwgenerator/funcs_charset.go | 39 +++++++++++++++++++++++++++++++++++- pwgenerator/funcs_genopts.go | 19 +++++++++++++----- 5 files changed, 116 insertions(+), 23 deletions(-) diff --git a/cmd/pwgen/args.go b/cmd/pwgen/args.go index 3899723..f111125 100644 --- a/cmd/pwgen/args.go +++ b/cmd/pwgen/args.go @@ -2,16 +2,17 @@ package main // Arguments contains the invocation arguments. type Arguments struct { - NoAlpha bool `short:"a" long:"disable-alpha" description:"If specified, do NOT include the Alphabetical (letter) charset."` - NoNum bool `short:"n" long:"disable-num" description:"If specified, do NOT include the Numerical (number) charset."` - NoSymbols bool `short:"s" long:"disable-symbols" description:"If specified, do NOT include the Simple Symbols charset."` - ExtendSymbols bool `short:"S" long:"enable-extended-symbols" description:"If specified, include the Extended Symbols charset (these characters may cause issues in some applications)."` - NumUpper uint `short:"u" long:"count-upper" description:"The number of minimum uppercase characters. If not specified, this is random (if in the charset)."` - NumLower uint `short:"U" long:"count-lower" description:"The number of minimum lowercase characters. If not specified, this is random (if in the charset)."` - NumSymbols uint `short:"y" long:"count-symbols" description:"The number of minimum simple symbol characters. If not specified, this is random (if in the charset)."` - NumExtended uint `short:"Y" long:"count-extended" description:"The number of minimum extended symbol characters. If not specified, this is random (if in the charset)."` - DisableChars uint `short:"d" long:"disable-chars" description:"If specified, this string of chars should be explicitly excluded from the charset(s)."` - MinLen uint `short:"l" long:"min-length" default:"16" description:"The minimum length for passwords; use 0 for no minimum limit. Set this to the same as -L/--max-length to use a fixed length."` - MaxLen uint `short:"L" long:"max-length" default:"64" description:"The maximum length for passwords; use 0 for no maximum limit (this is hard-capped to 256 for performance reasons). Set this to the same as -l/--min-length for a fixed length. Must be >= -l/--min-length."` - Count uint `short:"c" long:"count" default:"1" description:"The number of passwords to generate."` + NoAlpha bool `short:"a" long:"disable-alpha" description:"If specified, do NOT include the Alphabetical (letter) charset."` + NoNum bool `short:"n" long:"disable-num" description:"If specified, do NOT include the Numerical (number) charset."` + NoSymbols bool `short:"s" long:"disable-symbols" description:"If specified, do NOT include the Simple Symbols charset."` + ExtendSymbols bool `short:"S" long:"enable-extended-symbols" description:"If specified, include the Extended Symbols charset (these characters may cause issues in some applications)."` + NumUpper uint `short:"u" long:"count-upper" description:"The number of minimum uppercase characters. If not specified, this is random (if in the charset)."` + NumLower uint `short:"U" long:"count-lower" description:"The number of minimum lowercase characters. If not specified, this is random (if in the charset)."` + NumSymbols uint `short:"y" long:"count-symbols" description:"The number of minimum simple symbol characters. If not specified, this is random (if in the charset)."` + NumExtended uint `short:"Y" long:"count-extended" description:"The number of minimum extended symbol characters. If not specified, this is random (if in the charset)."` + DisableChars []string `short:"d" long:"disable-chars" description:"If specified, these chars should be explicitly excluded from the charset(s). Can be specified multiple times with multiple chars per switch."` + ExplicitChars []string `short:"e" long:"explicit-chars" description:"If specified, ignore all charset selection and only use these characters to select from. Can be specified multiple times."` + MinLen uint `short:"l" long:"min-length" default:"16" description:"The minimum length for passwords; use 0 for no minimum limit. Set this to the same as -L/--max-length to use a fixed length."` + MaxLen uint `short:"L" long:"max-length" default:"64" description:"The maximum length for passwords; use 0 for no maximum limit (this is hard-capped to 256 for performance reasons). Set this to the same as -l/--min-length for a fixed length. Must be >= -l/--min-length."` + Count uint `short:"c" long:"count" default:"1" description:"The number of passwords to generate."` } diff --git a/cmd/pwgen/main.go b/cmd/pwgen/main.go index 22041b5..86ea589 100644 --- a/cmd/pwgen/main.go +++ b/cmd/pwgen/main.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "os" + "strings" "github.com/jessevdk/go-flags" "r00t2.io/pwgen/pwgenerator" @@ -15,6 +16,7 @@ func main() { var err error var genOpts *pwgenerator.GenOpts + var passwds []string if _, err = flags.Parse(&a); err != nil { switch flagsErr := err.(type) { @@ -42,8 +44,23 @@ func main() { LengthMax: a.MaxLen, Count: a.Count, } + if a.DisableChars != nil && len(a.DisableChars) != 0 { + if genOpts.DisabledChars, err = pwgenerator.GetCharset(a.DisableChars); err != nil { + log.Panicln(err) + } + } + if a.ExplicitChars != nil && len(a.ExplicitChars) != 0 { + if err = genOpts.SetExplicitCharset(a.ExplicitChars, false); err != nil { + log.Panicln(err) + } + } - fmt.Printf("%#v\n", a) - fmt.Printf("%#v\n", genOpts) + if passwds, err = genOpts.Generate(); err != nil { + log.Panicln(err) + } + fmt.Println(strings.Join(passwds, "\n")) + + // fmt.Printf("%#v\n", a) + // fmt.Printf("%#v\n", genOpts) } diff --git a/pwgenerator/funcs.go b/pwgenerator/funcs.go index cd73d0a..9058365 100644 --- a/pwgenerator/funcs.go +++ b/pwgenerator/funcs.go @@ -1,12 +1,37 @@ package pwgenerator import ( - "bytes" "crypto/rand" "math/big" "sort" + "strings" ) +/* + GetCharset returns a CharSet from a set of characters. + + chars can be one of []rune, []byte, []string, or string. +*/ +func GetCharset(chars interface{}) (charset CharSet, err error) { + + switch t := chars.(type) { + case []rune: + charset = CharSet(string(t)) + case []byte: + charset = CharSet(string(t)) + case []string: + s := strings.Join(t, "") + charset = CharSet(s) + case string: + charset = CharSet(t) + default: + err = ErrBadType + return + } + + return +} + // sortDedupe sorts a slice of runes and deduplicates them. func sortDedupe(charset *CharSet) { @@ -42,12 +67,16 @@ func sortDedupe(charset *CharSet) { */ func saferRandInt(max int) (randInt int, err error) { + // Avoid a panic on max being 0 per rand.Int. + if max == 0 { + max = 1 + } + var max64 int64 = int64(max) var cryptoInt *big.Int = big.NewInt(max64) - var cryptoReader *bytes.Buffer = new(bytes.Buffer) var randInt64 int64 - if cryptoInt, err = rand.Int(cryptoReader, cryptoInt); err != nil { + if cryptoInt, err = rand.Int(rand.Reader, cryptoInt); err != nil { return } diff --git a/pwgenerator/funcs_charset.go b/pwgenerator/funcs_charset.go index b7d15dd..b088700 100644 --- a/pwgenerator/funcs_charset.go +++ b/pwgenerator/funcs_charset.go @@ -1,5 +1,42 @@ package pwgenerator +/* + Has returns true if a CharSet contains char. + + char can be one of: Char, byte, rune, or a string (of length 1). +*/ +func (c *CharSet) Has(char interface{}) (contains bool, err error) { + + var chkChar Char + + switch t := char.(type) { + case Char: + chkChar = t + case byte: + chkChar = Char(t) + case rune: + chkChar = Char(t) + case string: + if len(t) != 1 { + err = ErrBadType + return + } + chkChar = Char(t[0]) + default: + err = ErrBadType + return + } + + for _, i := range *c { + if chkChar == i { + contains = true + break + } + } + + return +} + // Len returns the length of a CharSet (needed for sort.Interface). func (c *CharSet) Len() (l int) { @@ -23,7 +60,7 @@ func (c *CharSet) RandChar() (char Char, err error) { var selectIdx int - if selectIdx, err = saferRandInt(len(*c) - 1); err != nil { + if selectIdx, err = saferRandInt(len(*c)); err != nil { return } diff --git a/pwgenerator/funcs_genopts.go b/pwgenerator/funcs_genopts.go index 636b388..cf884f0 100644 --- a/pwgenerator/funcs_genopts.go +++ b/pwgenerator/funcs_genopts.go @@ -71,14 +71,23 @@ func (o *GenOpts) generatePassword(c CharSet) (password string, err error) { // And make the rune slice of that length. passAlloc = make([]rune, passLen) - for _, idx := range passAlloc { + for idx, _ := range passAlloc { var char Char - if char, err = c.RandChar(); err != nil { - return - } + for { + var isDisabled bool - passAlloc[idx] = rune(char) + if char, err = c.RandChar(); err != nil { + return + } + if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled { + err = nil + continue + } + + passAlloc[idx] = rune(char) + break + } } password = string(passAlloc)