From 1d4d7c5538ef79267c5bd99af3dd9261ccf611ac Mon Sep 17 00:00:00 2001 From: brent s Date: Sun, 22 May 2022 04:43:12 -0400 Subject: [PATCH] -x, -f, env vars, prepping for hashing --- .githooks/post-commit/01-local_deploy.sh | 2 +- .gitignore | 3 ++ README.md | 42 +++++++++++------ TODO | 9 +++- build.sh | 13 ++++++ cmd/pwgen/args.go | 34 ++++++++------ cmd/pwgen/main.go | 42 ++++++++++++++--- cmd/pwverify/args.go | 6 +++ go.mod | 10 ++++- go.sum | 21 +++++++++ pwgenerator/consts.go | 14 ++++++ pwgenerator/funcs_genopts.go | 57 ++++++++++++++++++++++++ pwgenerator/types.go | 30 +++++++++++++ pwhash/funcs.go | 1 + pwhash/init.go | 16 +++++++ 15 files changed, 262 insertions(+), 38 deletions(-) create mode 100755 build.sh create mode 100644 cmd/pwverify/args.go create mode 100644 pwhash/funcs.go create mode 100644 pwhash/init.go diff --git a/.githooks/post-commit/01-local_deploy.sh b/.githooks/post-commit/01-local_deploy.sh index 0990c14..83fba97 100755 --- a/.githooks/post-commit/01-local_deploy.sh +++ b/.githooks/post-commit/01-local_deploy.sh @@ -2,6 +2,6 @@ set -e +cd "${PWD}/cmd/pwgen" mkdir -p ~/bin -cd ${PWD}/cmd/pwgen go build -o ~/bin/pwgen *.go diff --git a/.gitignore b/.gitignore index eafa7db..3d5ad41 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,9 @@ bin/* /pwgen /cmd/pwgen/pwgen +/pwgen_macos_m1.bin +/pwgen_macos_x86.bin +/pwgen_macos_x86_64.bin # Output of the go coverage tool, specifically when used with LiteIDE *.out diff --git a/README.md b/README.md index f1e63a7..78d901e 100644 --- a/README.md +++ b/README.md @@ -10,27 +10,41 @@ PWGen generates cryptographically-sound (i.e. non-predictable) passwords: * The order of characters in this generated password itself is then shuffled using `crypto/rand` as well. * This is done for every single password generated. +Invocation argument/flag defaults can be specified by the variable name in `[square brackets]`. e.g. the following in your `~/.bashrc`, for instance, on Linux: + +```text +export PWGEN_XLEN=32 +export PWGEN_NOSYM=1 +``` + +will by default always generate 32-character-long passwords that do not contain symbols. + +WIP: +It will also offers various hashing of the generated password(s) and a separate tool (`pwverify`) to verify a password against a hash. + All invocation options: ``` Usage: pwgen [OPTIONS] Application Options: - -a, --disable-alpha If specified, do NOT include the Alphabetical (letter) charset. - -n, --disable-num If specified, do NOT include the Numerical (number) charset. - -s, --disable-symbols If specified, do NOT include the Simple Symbols charset. - -S, --enable-extended-symbols If specified, include the Extended Symbols charset (these characters may cause issues in some applications). - -u, --count-upper= The number of minimum uppercase characters. If not specified, this is random (if in the charset). - -U, --count-lower= The number of minimum lowercase characters. If not specified, this is random (if in the charset). - -N, --count-numbers= The number of minimum number characters. If not specified, this is random (if in the charset). - -y, --count-symbols= The number of minimum simple symbol characters. If not specified, this is random (if in the charset). - -Y, --count-extended= The number of minimum extended symbol characters. If not specified, this is random (if in the charset). - -d, --disable-chars= If specified, these chars should be explicitly excluded from the charset(s). Can be specified multiple times with multiple chars per switch. - -e, --explicit-chars= If specified, ignore all charset selection and only use these characters to select from. Can be specified multiple times. - -l, --min-length= 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. Must be <= -L/--max-length. (default: 16) + -a, --disable-alpha If specified, do NOT include the Alphabetical (letter) charset. [$PWGEN_NOALPHA] + -n, --disable-num If specified, do NOT include the Numerical (number) charset. [$PWGEN_NONUM] + -s, --disable-symbols If specified, do NOT include the Simple Symbols charset. [$PWGEN_NOSYM] + -S, --enable-extended-symbols If specified, include the Extended Symbols charset (these characters may cause issues in some applications). [$PWGEN_XSYMS] + -u, --count-upper= The number of minimum uppercase characters. If not specified, this is random (if in the charset). [$PWGEN_UPPER] + -U, --count-lower= The number of minimum lowercase characters. If not specified, this is random (if in the charset). [$PWGEN_LOWER] + -N, --count-numbers= The number of minimum number characters. If not specified, this is random (if in the charset). [$PWGEN_NUMNUMS] + -y, --count-symbols= The number of minimum simple symbol characters. If not specified, this is random (if in the charset). [$PWGEN_NUMSYMS] + -Y, --count-extended= The number of minimum extended symbol characters. If not specified, this is random (if in the charset). [$PWGEN_NUMXSYMS] + -d, --disable-chars= If specified, these chars should be explicitly excluded from the charset(s). Can be specified multiple times with multiple chars per switch. [$PWGEN_NOCHARS] + -e, --explicit-chars= If specified, ignore all charset selection and only use these characters to select from. Can be specified multiple times. [$PWGEN_XCHARS] + -l, --min-length= 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. Must be <= -L/--max-length. (default: 16) [$PWGEN_MIN] -L, --max-length= 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. - (default: 64) - -c, --count= The number of passwords to generate. (default: 1) + (default: 64) [$PWGEN_MAX] + -x, --explicit-length= If specified, ignore -l/--min-length and -L/--max-length and set both to this length. [$PWGEN_XLEN] + -c, --count= The number of passwords to generate. (default: 1) [$PWGEN_CNT] + -f, --format=[json|yaml|xml] If specified, format the generated passwords in JSON (default), YAML, or XML. [$PWGEN_FMT] Help Options: -h, --help Show this help message diff --git a/TODO b/TODO index eb43fe9..b9015a3 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,16 @@ +- ~/.pwgenrc for defaults +-- add env var support for defaults as well + - whitespace (specifically, ' ') - "quick-format" options - json-safe/escaped, mysql-safe/escaped, etc. -- pretter printing for errors in main? +- prettier printing for errors in main? - "Human Readability"? - Hash/Salted hash generator +-- https://passlib.readthedocs.io/en/stable/lib/passlib.hash.html#module-passlib.hash +-- https://github.com/hlandau/passlib ? +--- missing from the above: +--- https://github.com/tg123/go-htpasswd diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..0410b60 --- /dev/null +++ b/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# PWGen +## Linux +go build -o pwgen cmd/pwgen/*.go +## Windows +env GOOS=windows go build -tags forceposix -o PWGen.exe cmd/pwgen/*.go +## macOS - x86_64 +env GOOS=darwin go build -o pwgen_macos_x86_64.bin cmd/pwgen/*.go +## macOS - ARM (M1) +env GOOS=darwin GOARCH=arm64 go build -o pwgen_macos_m1.bin cmd/pwgen/*.go + +# PWVerify (WIP) diff --git a/cmd/pwgen/args.go b/cmd/pwgen/args.go index 202a103..3741426 100644 --- a/cmd/pwgen/args.go +++ b/cmd/pwgen/args.go @@ -2,18 +2,24 @@ 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)."` - NumNumbers uint `short:"N" long:"count-numbers" description:"The number of minimum number 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. Must be <= -L/--max-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."` + /* + ListHashes bool `short:"z" long:"list-hashes" description:"If specified, list supported hashes and exit."` + Hashes []string `env:"PWGEN_HASHES" env-delim:"," short:"Z" long:"hash-algo" optional:"1" optional-value:"all" description:"Specify explicit hash algorithm(s). Can be specified multiple times. If this option is specified but no algorithms are provided, all hashes will be generated."` + */ + NoAlpha bool `env:"PWGEN_NOALPHA" short:"a" long:"disable-alpha" description:"If specified, do NOT include the Alphabetical (letter) charset."` + NoNum bool `env:"PWGEN_NONUM" short:"n" long:"disable-num" description:"If specified, do NOT include the Numerical (number) charset."` + NoSymbols bool `env:"PWGEN_NOSYM" short:"s" long:"disable-symbols" description:"If specified, do NOT include the Simple Symbols charset."` + ExtendSymbols bool `env:"PWGEN_XSYMS" short:"S" long:"enable-extended-symbols" description:"If specified, include the Extended Symbols charset (these characters may cause issues in some applications)."` + NumUpper uint `env:"PWGEN_UPPER" short:"u" long:"count-upper" description:"The number of minimum uppercase characters. If not specified, this is random (if in the charset)."` + NumLower uint `env:"PWGEN_LOWER" short:"U" long:"count-lower" description:"The number of minimum lowercase characters. If not specified, this is random (if in the charset)."` + NumNumbers uint `env:"PWGEN_NUMNUMS" short:"N" long:"count-numbers" description:"The number of minimum number characters. If not specified, this is random (if in the charset)."` + NumSymbols uint `env:"PWGEN_NUMSYMS" 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 `env:"PWGEN_NUMXSYMS" 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 `env:"PWGEN_NOCHARS" 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 `env:"PWGEN_XCHARS" 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 `env:"PWGEN_MIN" 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. Must be <= -L/--max-length."` + MaxLen uint `env:"PWGEN_MAX" 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."` + ExplicitLen uint `env:"PWGEN_XLEN" short:"x" long:"explicit-length" description:"If specified, ignore -l/--min-length and -L/--max-length and set both to this length."` + Count uint `env:"PWGEN_CNT" short:"c" long:"count" default:"1" description:"The number of passwords to generate."` + Format string `env:"PWGEN_FMT" short:"f" long:"format" optional:"1" optional-value:"json" choice:"json" choice:"yaml" choice:"xml" description:"If specified, format the generated passwords in JSON (default), YAML, or XML."` } diff --git a/cmd/pwgen/main.go b/cmd/pwgen/main.go index 14c197c..e7350d8 100644 --- a/cmd/pwgen/main.go +++ b/cmd/pwgen/main.go @@ -1,12 +1,15 @@ package main import ( + "encoding/json" + "encoding/xml" "fmt" "log" "os" "strings" "github.com/jessevdk/go-flags" + "gopkg.in/yaml.v3" "r00t2.io/pwgen/pwgenerator" ) @@ -17,6 +20,8 @@ func main() { var err error var genOpts *pwgenerator.GenOpts var passwds []string + var pwc *pwgenerator.PwCollection + var b []byte if _, err = flags.Parse(&a); err != nil { switch flagsErr := err.(type) { @@ -30,6 +35,10 @@ func main() { } } + if a.ExplicitLen != 0 { + a.MinLen = a.ExplicitLen + a.MaxLen = a.ExplicitLen + } genOpts = &pwgenerator.GenOpts{ Alpha: !a.NoAlpha, Numeric: !a.NoNum, @@ -56,12 +65,31 @@ func main() { } } - if passwds, err = genOpts.Generate(); err != nil { - log.Panicln(err) + if strings.TrimSpace(a.Format) != "" { + if pwc, err = genOpts.GenerateCollection(nil); err != nil { + log.Panicln(err) + } + switch a.Format { + case "json": + if b, err = json.MarshalIndent(pwc, "", " "); err != nil { + log.Panicln(err) + } + fmt.Println(string(b)) + case "yaml": + if b, err = yaml.Marshal(pwc); err != nil { + log.Panicln(err) + } + fmt.Println(string(b)) + case "xml": + if b, err = xml.MarshalIndent(pwc, "", " "); err != nil { + log.Panicln(err) + } + fmt.Println(string(b)) + } + } else { + if passwds, err = genOpts.Generate(); err != nil { + log.Panicln(err) + } + fmt.Println(strings.Join(passwds, "\n")) } - - fmt.Println(strings.Join(passwds, "\n")) - - // fmt.Printf("%#v\n", a) - // fmt.Printf("%#v\n", genOpts) } diff --git a/cmd/pwverify/args.go b/cmd/pwverify/args.go new file mode 100644 index 0000000..cc40048 --- /dev/null +++ b/cmd/pwverify/args.go @@ -0,0 +1,6 @@ +package main + +// Arguments contains the invocation arguments. +type Arguments struct { + ListHashes bool `short:"z" long:"list-hashes" description:"If specified, list supported hashes and exit."` +} diff --git a/go.mod b/go.mod index 5c44a08..fb2c69d 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,16 @@ module r00t2.io/pwgen go 1.17 require ( + github.com/hlandau/passlib v1.0.11 github.com/jessevdk/go-flags v1.5.0 + gopkg.in/yaml.v3 v3.0.0 r00t2.io/goutils v1.3.1 ) -require golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect +require ( + golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 // indirect + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + gopkg.in/hlandau/easymetric.v1 v1.0.0 // indirect + gopkg.in/hlandau/measurable.v1 v1.0.1 // indirect + gopkg.in/hlandau/passlib.v1 v1.0.11 // indirect +) diff --git a/go.sum b/go.sum index e77fc37..ca20d18 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,31 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hlandau/passlib v1.0.11 h1:GNcnM0Iwqx5M4IDCdKi9pJI/jmf6Z4NooIh8ND7rRBg= +github.com/hlandau/passlib v1.0.11/go.mod h1:77ovAz+VLR4VrRNrNhFTSSzYhZ4iUrGpXcBeC7cVRIU= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0= +golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/hlandau/easymetric.v1 v1.0.0 h1:ZbfbH7W3giuVDjWUoFhDOjjv20hiPr5HZ2yMV5f9IeE= +gopkg.in/hlandau/easymetric.v1 v1.0.0/go.mod h1:yh75hypuFzAxmvECh3ZKGCvFnIfapYJh2wv7ASaX2RE= +gopkg.in/hlandau/measurable.v1 v1.0.1 h1:wH5UZKCRUnRr1iD+xIZfwhtxhmr+bprRJttqA1Rklf4= +gopkg.in/hlandau/measurable.v1 v1.0.1/go.mod h1:6N+SYJGMTmetsx7wskULP+juuO+++tsHJkAgzvzsbuM= +gopkg.in/hlandau/passlib.v1 v1.0.11 h1:vKeHwGRdWBD9mm4bJ56GAAdBXpFUYvg/BYYkmphjnmA= +gopkg.in/hlandau/passlib.v1 v1.0.11/go.mod h1:wxGAv2CtQHlzWY8NJp+p045yl4WHyX7v2T6XbOcmqjM= +gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= r00t2.io/goutils v1.3.1 h1:mk8B2v7fM3gYoX64CDV206+/j8Z5iSJcszcPFjuvf3o= r00t2.io/goutils v1.3.1/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk= r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o= diff --git a/pwgenerator/consts.go b/pwgenerator/consts.go index 821c50e..7c8f2d8 100644 --- a/pwgenerator/consts.go +++ b/pwgenerator/consts.go @@ -7,6 +7,20 @@ const ( DefMinLin uint = 1 ) +// Hash algorithms. TODO. +const ( + HashNull pwHash = iota + HashArgon2i + HashScryptSha256 + HashCryptSha256 + HashCryptSha512 + HashBcrypt + HashBcryptSha256 + HashPbkdf2Sha1 + HashPbkdf2Sha256 + HashPbkdf2Sha512 +) + // Pre-defined charsets. var ( // upper contains the characters from 0x41 to 0x5a ([A-Z]). diff --git a/pwgenerator/funcs_genopts.go b/pwgenerator/funcs_genopts.go index a192dd5..a79eaa3 100644 --- a/pwgenerator/funcs_genopts.go +++ b/pwgenerator/funcs_genopts.go @@ -1,7 +1,9 @@ package pwgenerator import ( + "encoding/xml" "strings" + "time" "r00t2.io/goutils/multierr" ) @@ -44,6 +46,61 @@ func (o *GenOpts) Generate() (passwords []string, err error) { return } +/* + GenerateCollection returns a PwCollection instead of a slice of password text. + + It contains extended information about a password, hashes, etc. + + Note: hashing support currently under construction and not implemented. TODO. +*/ +func (o *GenOpts) GenerateCollection(hashAlgos []pwHash) (collection *PwCollection, err error) { + + var charset CharSet + var errs *multierr.MultiError = multierr.NewMultiError(nil) + var passwd string + + collection = &PwCollection{ + XMLName: xml.Name{ + Space: "", // TODO? + Local: "collection", + }, + Passwords: make([]*PwDef, o.Count), + } + + if o.Count == 0 { + o.Count = DefCount + } + if o.LengthMax == 0 { + o.LengthMax = DefMaxLen + } + + if err = o.sanChk(); err != nil { + return + } + + if charset, err = o.Chars(); err != nil { + return + } + + for idx, _ := range collection.Passwords { + if passwd, err = o.generatePassword(charset); err != nil { + errs.AddError(err) + err = nil + } + collection.Passwords[idx] = &PwDef{ + XMLName: xml.Name{ + Space: "", // TODO? + Local: "password", + }, + Password: passwd, + Generated: time.Now(), + Hashes: nil, // TODO + } + } + + return +} + // generatePassword generates a single password from CharSet c (plus any minimum requirements). func (o *GenOpts) generatePassword(c CharSet) (password string, err error) { diff --git a/pwgenerator/types.go b/pwgenerator/types.go index 590f70e..38def37 100644 --- a/pwgenerator/types.go +++ b/pwgenerator/types.go @@ -1,5 +1,13 @@ package pwgenerator +import ( + "encoding/xml" + "time" +) + +// pwHash is an explicit hash algorithm. +type pwHash uint8 + // cryptoShuffler is used to shuffle a slice in a cryptographically sane way. type cryptoShuffler struct{} @@ -56,6 +64,28 @@ type GenOpts struct { explicitCharset CharSet } +// PwCollection contains the full series of generated passwords. +type PwCollection struct { + XMLName xml.Name `json:"-" yaml:"-"` + Passwords []*PwDef `json:"password_defs" yaml:"Password Definitions" xml:"passwordDefs"` +} + +// PwDef contains a generated password and related metadata. +type PwDef struct { + XMLName xml.Name `json:"-" yaml:"-"` + Password string `json:"password" yaml:"Password" xml:"password,attr"` + Generated time.Time `json:"generated" yaml:"Generated" xml:"generated,attr"` + Hashes []PwHashDef `json:"hashes,omitempty" yaml:"Hashes,omitempty" xml:"hashes,omitempty"` + // Hashes []PwHashDef `json:"hashes" yaml:"Hashes" xml:"hashes"` +} + +// PwHashDef defines a hash for a PwDef (once we implement it). +type PwHashDef struct { + XMLName xml.Name `json:"-" yaml:"-"` + HashType string `json:"hash_algo" yaml:"Hash Algorithm" xml:"hashAlgo,attr"` + HashString string `json:"hash" yaml:"Hash" xml:",chardata"` +} + // selectFilter is used to include specified number of characters. type selectFilter struct { upperCounter uint diff --git a/pwhash/funcs.go b/pwhash/funcs.go new file mode 100644 index 0000000..7191df8 --- /dev/null +++ b/pwhash/funcs.go @@ -0,0 +1 @@ +package pwhash diff --git a/pwhash/init.go b/pwhash/init.go new file mode 100644 index 0000000..c7e9715 --- /dev/null +++ b/pwhash/init.go @@ -0,0 +1,16 @@ +package pwhash + +import ( + "github.com/hlandau/passlib" +) + +// init initializes the hashing libraries where necessary. +func init() { + + var err error + + if err = passlib.UseDefaults("latest"); err != nil { + panic(err) + } + +}