char mins done; need to shuffle some error condition checks before

This commit is contained in:
2022-03-04 01:04:14 -05:00
parent 77d5271b5a
commit 1c0481824e
9 changed files with 215 additions and 16 deletions

View File

@@ -36,7 +36,7 @@ func (o *GenOpts) Generate() (passwords []string, err error) {
return
}
// generatePassword generates a single password from CharSet c.
// generatePassword generates a single password from CharSet c (plus any minimum requirements).
func (o *GenOpts) generatePassword(c CharSet) (password string, err error) {
var maxMin uint
@@ -44,9 +44,33 @@ func (o *GenOpts) generatePassword(c CharSet) (password string, err error) {
var passLenGap uint
var passLen int
var passAlloc []rune
var filter *selectFilter = o.getFilter()
var isDisabled bool
// Sanity checks/error conditions.
maxMin = o.CountUpper + o.CountLower + o.CountSymbols + o.CountExtended
if o.explicitCharset != nil && len(o.explicitCharset) != 0 {
if o.CountUpper > 0 && !o.Alpha {
err = ErrIncompatCharsetFilter
return
}
if o.CountLower > 0 && !o.Alpha {
err = ErrIncompatCharsetFilter
return
}
if o.CountNumbers > 0 && !o.Numeric {
err = ErrIncompatCharsetFilter
return
}
if o.CountSymbols > 0 && !o.Symbols {
err = ErrIncompatCharsetFilter
return
}
if o.CountExtended > 0 && !o.ExtendedSymbols {
err = ErrIncompatCharsetFilter
return
}
}
maxMin = o.CountUpper + o.CountLower + o.CountNumbers + o.CountSymbols + o.CountExtended
if maxMin > o.LengthMax {
err = ErrTooSmall
return
@@ -71,11 +95,93 @@ 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 {
idx := 0
for idx < passLen {
var char Char
if o.explicitCharset != nil && len(o.explicitCharset) != 0 {
// Add upperCounter chars (if necessary).
for filter.upperCounter > 0 {
if char, err = upper.RandChar(); err != nil {
continue
}
if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled {
err = nil
continue
}
passAlloc[idx] = rune(char)
filter.upperCounter--
idx++
continue
}
// Add lowerCounter chars (if necessary).
for filter.lowerCounter > 0 {
if char, err = lower.RandChar(); err != nil {
continue
}
if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled {
err = nil
continue
}
passAlloc[idx] = rune(char)
filter.lowerCounter--
idx++
continue
}
// Add numberCounter chars (if necessary).
for filter.numberCounter > 0 {
if char, err = numeric.RandChar(); err != nil {
continue
}
if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled {
err = nil
continue
}
passAlloc[idx] = rune(char)
filter.numberCounter--
idx++
continue
}
// Add symbolCounter chars (if necessary).
for filter.symbolCounter > 0 {
if char, err = symbols.RandChar(); err != nil {
continue
}
if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled {
err = nil
continue
}
passAlloc[idx] = rune(char)
filter.symbolCounter--
idx++
continue
}
// Add extendedCounter chars (if necessary).
for filter.extendedCounter > 0 {
if char, err = extendedSymbols.RandChar(); err != nil {
continue
}
if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled {
err = nil
continue
}
passAlloc[idx] = rune(char)
filter.extendedCounter--
idx++
continue
}
// Break here if we've reached the full password with just the filter.
if idx > passLen {
err = ErrTooSmall
return
} else if idx == passLen {
break
}
}
// Minimum requirements satisfied; continue with default GenOpts-specific charset.
for {
var isDisabled bool
if char, err = c.RandChar(); err != nil {
return
@@ -86,11 +192,13 @@ func (o *GenOpts) generatePassword(c CharSet) (password string, err error) {
}
passAlloc[idx] = rune(char)
idx++
break
}
}
password = string(passAlloc)
passwordShuffle(&password)
return
}
@@ -182,3 +290,17 @@ func (o *GenOpts) UnsetExplicitCharset() {
return
}
// getFilter gets a filter counter.
func (o *GenOpts) getFilter() (f *selectFilter) {
f = &selectFilter{
upperCounter: o.CountUpper,
lowerCounter: o.CountLower,
numberCounter: o.CountNumbers,
symbolCounter: o.CountSymbols,
extendedCounter: o.CountExtended,
}
return
}