before adding cryptoshuffler

This commit is contained in:
brent s. 2022-03-03 05:51:22 -05:00
parent 480dcd7e24
commit 77d5271b5a
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
5 changed files with 116 additions and 23 deletions

View File

@ -10,7 +10,8 @@ type Arguments struct {
NumLower uint `short:"U" long:"count-lower" description:"The number of minimum lowercase 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)."` 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)."` 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)."` 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."` 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."` 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."` Count uint `short:"c" long:"count" default:"1" description:"The number of passwords to generate."`

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"strings"


"github.com/jessevdk/go-flags" "github.com/jessevdk/go-flags"
"r00t2.io/pwgen/pwgenerator" "r00t2.io/pwgen/pwgenerator"
@ -15,6 +16,7 @@ func main() {


var err error var err error
var genOpts *pwgenerator.GenOpts var genOpts *pwgenerator.GenOpts
var passwds []string


if _, err = flags.Parse(&a); err != nil { if _, err = flags.Parse(&a); err != nil {
switch flagsErr := err.(type) { switch flagsErr := err.(type) {
@ -42,8 +44,23 @@ func main() {
LengthMax: a.MaxLen, LengthMax: a.MaxLen,
Count: a.Count, Count: a.Count,
} }

if a.DisableChars != nil && len(a.DisableChars) != 0 {
fmt.Printf("%#v\n", a) if genOpts.DisabledChars, err = pwgenerator.GetCharset(a.DisableChars); err != nil {
fmt.Printf("%#v\n", genOpts) log.Panicln(err)

}
}
if a.ExplicitChars != nil && len(a.ExplicitChars) != 0 {
if err = genOpts.SetExplicitCharset(a.ExplicitChars, false); err != nil {
log.Panicln(err)
}
}

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)
} }

View File

@ -1,12 +1,37 @@
package pwgenerator package pwgenerator


import ( import (
"bytes"
"crypto/rand" "crypto/rand"
"math/big" "math/big"
"sort" "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. // sortDedupe sorts a slice of runes and deduplicates them.
func sortDedupe(charset *CharSet) { func sortDedupe(charset *CharSet) {


@ -42,12 +67,16 @@ func sortDedupe(charset *CharSet) {
*/ */
func saferRandInt(max int) (randInt int, err error) { 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 max64 int64 = int64(max)
var cryptoInt *big.Int = big.NewInt(max64) var cryptoInt *big.Int = big.NewInt(max64)
var cryptoReader *bytes.Buffer = new(bytes.Buffer)
var randInt64 int64 var randInt64 int64


if cryptoInt, err = rand.Int(cryptoReader, cryptoInt); err != nil { if cryptoInt, err = rand.Int(rand.Reader, cryptoInt); err != nil {
return return
} }



View File

@ -1,5 +1,42 @@
package pwgenerator 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). // Len returns the length of a CharSet (needed for sort.Interface).
func (c *CharSet) Len() (l int) { func (c *CharSet) Len() (l int) {


@ -23,7 +60,7 @@ func (c *CharSet) RandChar() (char Char, err error) {


var selectIdx int var selectIdx int


if selectIdx, err = saferRandInt(len(*c) - 1); err != nil { if selectIdx, err = saferRandInt(len(*c)); err != nil {
return return
} }



View File

@ -71,14 +71,23 @@ func (o *GenOpts) generatePassword(c CharSet) (password string, err error) {
// And make the rune slice of that length. // And make the rune slice of that length.
passAlloc = make([]rune, passLen) passAlloc = make([]rune, passLen)


for _, idx := range passAlloc { for idx, _ := range passAlloc {
var char Char var char Char


for {
var isDisabled bool

if char, err = c.RandChar(); err != nil { if char, err = c.RandChar(); err != nil {
return return
} }
if isDisabled, err = o.DisabledChars.Has(char); err != nil || isDisabled {
err = nil
continue
}


passAlloc[idx] = rune(char) passAlloc[idx] = rune(char)
break
}
} }


password = string(passAlloc) password = string(passAlloc)