diff --git a/.gitignore b/.gitignore index 57bc138..12eb2e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ *.idea -cmd/gophrase/gophrase \ No newline at end of file +src/gophrase \ No newline at end of file diff --git a/assets/defaults.json b/assets/defaults.json deleted file mode 100644 index 2f8ee80..0000000 --- a/assets/defaults.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "wordCount": 5, - "wordList": "eff_short_wordlist_2_0.json" -} \ No newline at end of file diff --git a/cmd/gophrase/main.go b/cmd/gophrase/main.go deleted file mode 100644 index 582cbc5..0000000 --- a/cmd/gophrase/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "github.com/gophrase/internal" - "github.com/gophrase/internal/argument" - "github.com/urfave/cli/v2" - "log" - "os" -) - -func main() { - app := *cli.NewApp() - app.Name = internal.APP_NAME - app.Usage = internal.APP_USAGE - app.UsageText = internal.APP_USAGETEXT - app.Version = internal.APP_VERSION - app.HideHelp = false - app.HideVersion = false - app.Commands = argument.Commands - err := app.Run(os.Args) - if err != nil { - log.Fatal(err) - } -} diff --git a/go.mod b/go.mod deleted file mode 100644 index 5e772b6..0000000 --- a/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module github.com/gophrase - -go 1.13 - -require ( - github.com/gobuffalo/packr/v2 v2.8.0 - github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d - github.com/urfave/cli/v2 v2.1.1 - golang.org/x/tools v0.0.0-20200308013534-11ec41452d41 -) diff --git a/internal/constant.go b/internal/constant.go deleted file mode 100644 index 5e53031..0000000 --- a/internal/constant.go +++ /dev/null @@ -1,16 +0,0 @@ -package internal - -// App information constants -const APP_NAME = "Go Phrase" -const APP_USAGE = "CLI for generating secure, memorable passwords" -const APP_VERSION = "v1.0.0 | release: 5.10.20" -const APP_USAGETEXT = "gophrase gen [word count] [word list] [--flags]" - -// Static asset constants -const EFF_LARGE = "eff_large_wordlist.json" -const EFF_SHORT_1 = "eff_short_wordlist_1.json" -const EFF_SHORT_2 = "eff_short_wordlist_2_0.json" -const REINHOLD = "reinhold_wordlist.json" -const CHARACTERS = "special_characters.json" -const LIST_OPTIONS = "list_options.txt" -const DEFAULTS = "defaults.json" diff --git a/pkg/config/config.go b/pkg/config/config.go deleted file mode 100644 index 7525b70..0000000 --- a/pkg/config/config.go +++ /dev/null @@ -1,47 +0,0 @@ -package config - -import ( - "encoding/json" - "fmt" - "github.com/gobuffalo/packr/v2" - "github.com/gophrase/internal" - "io/ioutil" - "log" -) - -type Default struct { - WordCount int `json:"wordCount"` - WordList string `json:"wordList"` -} - -var Assets = packr.New("assets", "../../assets") -var Defaults = new(Default) - -func SetConfigDefaults(config *Default, count int, list string) { - fileLocation := internal.DEFAULTS //TODO create better implementation - config.WordCount = count - config.WordList = list - file, err := json.MarshalIndent(config, "", "\t") - if err != nil { - log.Fatal(err) - } - err = ioutil.WriteFile("../../assets/"+fileLocation, file, 0644) - if err != nil { - log.Fatal(err) - } -} - -func LoadConfigDefaults() { - fileLocation, err := Assets.Find(internal.DEFAULTS) - if err != nil { - log.Fatal(err) - } - err = json.Unmarshal(fileLocation, &Defaults) - if err != nil { - log.Fatal(err) - } -} - -func PrintConfigDefaults(config *Default) { - fmt.Printf("Word Count: %d \nWord List: %s \n", config.WordCount, config.WordList) -} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go deleted file mode 100644 index e4df9b0..0000000 --- a/pkg/config/config_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package config - -import ( - "github.com/gophrase/internal" - "testing" -) - -func TestPrintConfigDefaults(t *testing.T) { - var defaults = Default{ - WordCount: 3, - WordList: internal.EFF_SHORT_2, - } - PrintConfigDefaults(&defaults) -} diff --git a/pkg/corpus/corpus.go b/pkg/corpus/corpus.go deleted file mode 100644 index 27fce6d..0000000 --- a/pkg/corpus/corpus.go +++ /dev/null @@ -1,73 +0,0 @@ -package corpus - -import ( - "encoding/json" - "github.com/gophrase/internal" - "github.com/gophrase/pkg/config" - "log" - "math/rand" - "time" -) - -func getSpecialCharList() []byte { - fileLocation, err := config.Assets.Find(internal.CHARACTERS) - if err != nil { - log.Fatal(err) - } - return fileLocation -} - -func GetSpecialChar() string { - rand.Seed(time.Now().UnixNano()) - chars := make(map[int]string) - corpus := getSpecialCharList() - err := json.Unmarshal(corpus, &chars) - if err != nil { - log.Fatal(err) - } - key := rand.Intn(len(chars)) + 1 - return chars[key] -} - -func getWordList(wordlist string) []byte { - fileLocation, err := config.Assets.Find(SetWordList(wordlist)) - if err != nil { - log.Fatal(err) - } - return fileLocation -} - -func GetWord(key int, wordlist string) string { - words := make(map[int]string) - corpus := getWordList(wordlist) - err := json.Unmarshal(corpus, &words) - if err != nil { - log.Fatal(err) - } - word := words[key] - return word -} - -func SetWordList(wordlist string) string { - // This is organized by my personal preference. - switch list := wordlist; list { - case "a": - return internal.EFF_SHORT_2 - case "b": - return internal.EFF_SHORT_1 - case "c": - return internal.EFF_LARGE - case "d": - return internal.REINHOLD - default: - return config.Defaults.WordList - } -} - -func PrintWordListOptions() []byte { - fileLocation, err := config.Assets.Find(internal.LIST_OPTIONS) - if err != nil { - log.Fatal(err) - } - return fileLocation -} diff --git a/src/assets/config/config.yaml b/src/assets/config/config.yaml new file mode 100644 index 0000000..c6c46b0 --- /dev/null +++ b/src/assets/config/config.yaml @@ -0,0 +1,5 @@ +WordCount: 5 +WordList: assets/wordlists/eff_short_wordlist_1.json +Capital: false +Special: false +Number: false diff --git a/assets/list_options.txt b/src/assets/list_options.txt similarity index 85% rename from assets/list_options.txt rename to src/assets/list_options.txt index c2b9daf..e514921 100644 --- a/assets/list_options.txt +++ b/src/assets/list_options.txt @@ -2,8 +2,8 @@ Wordlist Options To set the list `gophrase gen 5 a` or `gophrase gen a` if you are okay with a three word passphrase. -a: EFF Short Wordlist 2 -b: EFF Short Wordlist 1 +a: EFF Short Wordlist 1 +b: EFF Short Wordlist 2 c: EFF Large Wordlist d: Reinhold Wordlist diff --git a/assets/eff_large_wordlist.json b/src/assets/wordlists/eff_large_wordlist.json similarity index 100% rename from assets/eff_large_wordlist.json rename to src/assets/wordlists/eff_large_wordlist.json diff --git a/assets/eff_short_wordlist_1.json b/src/assets/wordlists/eff_short_wordlist_1.json similarity index 100% rename from assets/eff_short_wordlist_1.json rename to src/assets/wordlists/eff_short_wordlist_1.json diff --git a/assets/eff_short_wordlist_2_0.json b/src/assets/wordlists/eff_short_wordlist_2.json similarity index 100% rename from assets/eff_short_wordlist_2_0.json rename to src/assets/wordlists/eff_short_wordlist_2.json diff --git a/assets/reinhold_wordlist.json b/src/assets/wordlists/reinhold_wordlist.json similarity index 100% rename from assets/reinhold_wordlist.json rename to src/assets/wordlists/reinhold_wordlist.json diff --git a/assets/special_characters.json b/src/assets/wordlists/special_characters.json similarity index 100% rename from assets/special_characters.json rename to src/assets/wordlists/special_characters.json diff --git a/internal/argument/command.go b/src/command/command.go similarity index 51% rename from internal/argument/command.go rename to src/command/command.go index b460e6c..510428a 100644 --- a/internal/argument/command.go +++ b/src/command/command.go @@ -1,15 +1,20 @@ -package argument +package command import ( "fmt" - "github.com/gophrase/pkg/config" - "github.com/gophrase/pkg/corpus" - "github.com/gophrase/pkg/entropy" - "github.com/gophrase/pkg/generate" + "github.com/jmillerv/gophrase/config" + "github.com/jmillerv/gophrase/corpus" + "github.com/jmillerv/gophrase/entropy" + "github.com/jmillerv/gophrase/generate" "github.com/urfave/cli/v2" "strconv" ) +const ( + defaultWordCount = 5 +) + +// Commands hold an array of cli.Commands which are used to run the CLI application. var Commands = []*cli.Command{ { Name: "generate", @@ -17,32 +22,32 @@ var Commands = []*cli.Command{ Usage: "gen [int]", Action: func(c *cli.Context) error { // TODO input validator to clean up section - config.LoadConfigDefaults() - p := generate.Params{} + config.LoadConfig() + p := &generate.Params{} p.WordCount, _ = strconv.Atoi(c.Args().Get(0)) if p.WordCount == 0 { - p.WordCount = config.Defaults.WordCount + p.WordCount = config.LoadedConfig.WordCount } p.WordList = c.Args().Get(1) if p.WordList == "" { - p.WordList = config.Defaults.WordList + p.WordList = config.LoadedConfig.WordList } - if c.Bool("capital") { + if c.Bool("capital") || config.LoadedConfig.Capital { p.Capitals = true } else { p.Capitals = false } - if c.Bool("special") { + if c.Bool("special") || config.LoadedConfig.Special { p.SpecialChars = true } else { p.SpecialChars = false } - if c.Bool("number") { + if c.Bool("number") || config.LoadedConfig.Number { p.Numbers = true } else { p.Numbers = false } - password := generate.Password(&p) + password := generate.Password(p) entropy.PrintEntropy(password) return nil }, @@ -65,7 +70,7 @@ var Commands = []*cli.Command{ }, }, { - Name: "Wordlist Options", + Name: "wordlist-options", Aliases: []string{"opts"}, Usage: "View the wordlist options for passphrase generation", Action: func(c *cli.Context) error { @@ -74,30 +79,56 @@ var Commands = []*cli.Command{ }, }, { - Name: "Set Defaults", + Name: "set-defaults", Aliases: []string{"sd"}, Usage: "Set default options for word count and word list", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "capital", + Aliases: []string{"c"}, + Usage: "Add random capitalization to your passwords", + }, + &cli.BoolFlag{ + Name: "special", + Aliases: []string{"s"}, + Usage: "Add random special characters to your passwords", + }, + &cli.BoolFlag{ + Name: "number", + Aliases: []string{"n"}, + Usage: "Add numbers to your passwords", + }, + }, Action: func(c *cli.Context) error { - p := generate.Params{} - p.WordCount, _ = strconv.Atoi(c.Args().Get(0)) - if p.WordCount == 0 { - p.WordCount = config.Defaults.WordCount + conf := &config.Config{} + conf.WordCount, _ = strconv.Atoi(c.Args().Get(0)) + if conf.WordCount == 0 { + conf.WordCount = defaultWordCount } - p.WordList = corpus.SetWordList(c.Args().Get(1)) - if p.WordList == "" { - p.WordList = config.Defaults.WordList + conf.WordList = corpus.SetWordList(c.Args().Get(1)) + if conf.WordList == "" { + conf.WordList = config.EffShort1 + } + if c.Bool("capital") { + conf.Capital = true + } + if c.Bool("special") { + conf.Special = true + } + if c.Bool("number") { + conf.Number = true } - config.SetConfigDefaults(config.Defaults, p.WordCount, p.WordList) + config.SetConfig(conf) return nil }, }, { - Name: "List Defaults", + Name: "list-defaults", Aliases: []string{"ld"}, Usage: "Print default options for word count and word list", Action: func(c *cli.Context) error { - config.LoadConfigDefaults() - config.PrintConfigDefaults(config.Defaults) + config.LoadConfig() + config.LoadedConfig.PrintConfig() return nil }, }, diff --git a/src/config/config.go b/src/config/config.go new file mode 100644 index 0000000..582d0ce --- /dev/null +++ b/src/config/config.go @@ -0,0 +1,65 @@ +package config + +import ( + "embed" + "github.com/jmillerv/go-utilities/format" + "gopkg.in/yaml.v3" + "io/ioutil" + "log" +) + +// Static asset constants +const ( + EffLarge = "assets/wordlists/eff_large_wordlist.json" + EffShort1 = "assets/wordlists/eff_short_wordlist_1.json" + EffShort2 = "assets/wordlists/eff_short_wordlist_2.json" + Reinhold = "assets/wordlists/reinhold_wordlist.json" + Characters = "assets/wordlists/special_characters.json" + ListOptions = "assets/list_options.txt" + Configuration = "assets/config/config.yaml" +) + +// Assets is the embed.FS file system to access embedded files throughout the application. +var Assets embed.FS + +// LoadedConfig is the configuration for gophrase throuhgout the application. +var LoadedConfig = new(Config) + +// Config holds the values from a configuration file for default generation settings. +type Config struct { + WordCount int `yaml:"WordCount"` + WordList string `yaml:"WordList"` + Capital bool `yaml:"Capital"` + Special bool `yaml:"Special"` + Number bool `yaml:"Number"` +} + +// PrintConfig outputs the current config to the console +func (c *Config) PrintConfig() { + log.Print(format.StructToIndentedString(c)) +} + +// SetConfig takes in a config and writes it to the configuration file. +func SetConfig(config *Config) { + fileLocation := Configuration + file, err := yaml.Marshal(config) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(fileLocation, file, 0644) + if err != nil { + log.Fatal(err) + } +} + +// LoadConfig reads a configuration file and loads it into the LoadedConfig variable. +func LoadConfig() { + fileLocation, err := Assets.ReadFile(Configuration) + if err != nil { + log.Fatal(err) + } + err = yaml.Unmarshal(fileLocation, &LoadedConfig) + if err != nil { + log.Fatal(err) + } +} diff --git a/src/config/config_test.go b/src/config/config_test.go new file mode 100644 index 0000000..d912156 --- /dev/null +++ b/src/config/config_test.go @@ -0,0 +1 @@ +package config diff --git a/src/corpus/corpus.go b/src/corpus/corpus.go new file mode 100644 index 0000000..55fee5e --- /dev/null +++ b/src/corpus/corpus.go @@ -0,0 +1,75 @@ +package corpus + +import ( + "encoding/json" + "github.com/jmillerv/gophrase/config" + log "github.com/sirupsen/logrus" + "math/rand" + "time" +) + +func getSpecialCharList() []byte { + fileLocation, err := config.Assets.ReadFile("../" + config.Characters) + if err != nil { + log.WithField("function", "getSpecialCharList").WithError(err).Fatal("unable to load special characters") + } + return fileLocation +} + +// GetSpecialChar retrieves a special character from the special_characters.json +func GetSpecialChar() string { + rand.Seed(time.Now().UnixNano()) + chars := make(map[int]string) + corpus := getSpecialCharList() + err := json.Unmarshal(corpus, &chars) + if err != nil { + log.WithError(err).Fatal("json.Unmarshal") + } + key := rand.Intn(len(chars)) + 1 + return chars[key] +} + +func getWordList(wordlist string) []byte { + fileLocation, err := config.Assets.ReadFile(wordlist) + if err != nil { + log.WithError(err).Fatal("unable to read file") + } + return fileLocation +} + +// GetWord retrieves a word from the passed in wordlist +func GetWord(key int, wordlist string) string { + words := make(map[int]string) + corpus := getWordList(wordlist) + err := json.Unmarshal(corpus, &words) + if err != nil { + log.WithField("function", "GetWord").WithError(err).Fatal("json.Unmarshal") + } + word := words[key] + return word +} + +// SetWordList updates the LoadedConfig.Wordlist property +func SetWordList(wordlist string) string { + switch list := wordlist; list { + case "a": + return config.EffShort1 + case "b": + return config.EffShort2 + case "c": + return config.EffLarge + case "d": + return config.Reinhold + default: + return config.LoadedConfig.WordList + } +} + +// PrintWordListOptions prints wordlist documentation to the console. +func PrintWordListOptions() []byte { + fileLocation, err := config.Assets.ReadFile(config.ListOptions) + if err != nil { + log.WithField("function", "PrintWordListOptions").WithError(err).Error("unable to read file") + } + return fileLocation +} diff --git a/pkg/corpus/corpus_test.go b/src/corpus/corpus_test.go similarity index 76% rename from pkg/corpus/corpus_test.go rename to src/corpus/corpus_test.go index c026906..db263cf 100644 --- a/pkg/corpus/corpus_test.go +++ b/src/corpus/corpus_test.go @@ -1,7 +1,7 @@ package corpus import ( - "github.com/gophrase/internal" + "github.com/jmillerv/gophrase/config" "testing" ) @@ -27,19 +27,19 @@ func TestSetWordList(t *testing.T) { var testValues = tables{"a", "b", "c", "d", ""} - if SetWordList(testValues.first) != internal.EFF_SHORT_2 { + if SetWordList(testValues.first) != config.EffShort2 { t.Errorf("SetWordList() failed expected 'eff_short_wordlist_2_0.json', but got %s", SetWordList(testValues.first)) } - if SetWordList(testValues.second) != internal.EFF_SHORT_1 { + if SetWordList(testValues.second) != config.EffShort1 { t.Errorf("SetWordList() failed expected 'eff_short_wordlist_1.json', but got %s", SetWordList(testValues.second)) } - if SetWordList(testValues.third) != internal.EFF_LARGE { + if SetWordList(testValues.third) != config.EffLarge { t.Errorf("SetWordList() failed expected 'eff_large_wordlist.json', but got %s", SetWordList(testValues.third)) } - if SetWordList(testValues.fourth) != internal.REINHOLD { + if SetWordList(testValues.fourth) != config.Reinhold { t.Errorf("SetWordList() failed expected 'reinhold_wordlist.json', but got %s", SetWordList(testValues.fourth)) } - if SetWordList(testValues.fifth) != internal.EFF_SHORT_2 { + if SetWordList(testValues.fifth) != config.EffShort1 { t.Errorf("SetWordList() failed expected 'eff_short_wordlist_2_0.json', but got %s", SetWordList(testValues.fifth)) } } diff --git a/embedded_licenses/github.com/cpuguy83/go-md2man/v2/md2man/LICENSE.md b/src/embedded_licenses/github.com/cpuguy83/go-md2man/v2/md2man/LICENSE.md similarity index 100% rename from embedded_licenses/github.com/cpuguy83/go-md2man/v2/md2man/LICENSE.md rename to src/embedded_licenses/github.com/cpuguy83/go-md2man/v2/md2man/LICENSE.md diff --git a/embedded_licenses/github.com/gobuffalo/logger/LICENSE b/src/embedded_licenses/github.com/gobuffalo/logger/LICENSE similarity index 100% rename from embedded_licenses/github.com/gobuffalo/logger/LICENSE rename to src/embedded_licenses/github.com/gobuffalo/logger/LICENSE diff --git a/embedded_licenses/github.com/gobuffalo/packd/LICENSE b/src/embedded_licenses/github.com/gobuffalo/packd/LICENSE similarity index 100% rename from embedded_licenses/github.com/gobuffalo/packd/LICENSE rename to src/embedded_licenses/github.com/gobuffalo/packd/LICENSE diff --git a/embedded_licenses/github.com/gobuffalo/packd/internal/takeon/github.com/markbates/errx/LICENSE b/src/embedded_licenses/github.com/gobuffalo/packd/internal/takeon/github.com/markbates/errx/LICENSE similarity index 100% rename from embedded_licenses/github.com/gobuffalo/packd/internal/takeon/github.com/markbates/errx/LICENSE rename to src/embedded_licenses/github.com/gobuffalo/packd/internal/takeon/github.com/markbates/errx/LICENSE diff --git a/embedded_licenses/github.com/gobuffalo/packr/v2/LICENSE.txt b/src/embedded_licenses/github.com/gobuffalo/packr/v2/LICENSE.txt similarity index 100% rename from embedded_licenses/github.com/gobuffalo/packr/v2/LICENSE.txt rename to src/embedded_licenses/github.com/gobuffalo/packr/v2/LICENSE.txt diff --git a/embedded_licenses/github.com/karrick/godirwalk/LICENSE b/src/embedded_licenses/github.com/karrick/godirwalk/LICENSE similarity index 100% rename from embedded_licenses/github.com/karrick/godirwalk/LICENSE rename to src/embedded_licenses/github.com/karrick/godirwalk/LICENSE diff --git a/embedded_licenses/github.com/markbates/errx/LICENSE b/src/embedded_licenses/github.com/markbates/errx/LICENSE similarity index 100% rename from embedded_licenses/github.com/markbates/errx/LICENSE rename to src/embedded_licenses/github.com/markbates/errx/LICENSE diff --git a/embedded_licenses/github.com/markbates/oncer/LICENSE b/src/embedded_licenses/github.com/markbates/oncer/LICENSE similarity index 100% rename from embedded_licenses/github.com/markbates/oncer/LICENSE rename to src/embedded_licenses/github.com/markbates/oncer/LICENSE diff --git a/embedded_licenses/github.com/markbates/safe/LICENSE b/src/embedded_licenses/github.com/markbates/safe/LICENSE similarity index 100% rename from embedded_licenses/github.com/markbates/safe/LICENSE rename to src/embedded_licenses/github.com/markbates/safe/LICENSE diff --git a/embedded_licenses/github.com/nbutton23/zxcvbn-go/LICENSE.txt b/src/embedded_licenses/github.com/nbutton23/zxcvbn-go/LICENSE.txt similarity index 100% rename from embedded_licenses/github.com/nbutton23/zxcvbn-go/LICENSE.txt rename to src/embedded_licenses/github.com/nbutton23/zxcvbn-go/LICENSE.txt diff --git a/embedded_licenses/github.com/russross/blackfriday/v2/LICENSE.txt b/src/embedded_licenses/github.com/russross/blackfriday/v2/LICENSE.txt similarity index 100% rename from embedded_licenses/github.com/russross/blackfriday/v2/LICENSE.txt rename to src/embedded_licenses/github.com/russross/blackfriday/v2/LICENSE.txt diff --git a/embedded_licenses/github.com/shurcooL/sanitized_anchor_name/LICENSE b/src/embedded_licenses/github.com/shurcooL/sanitized_anchor_name/LICENSE similarity index 100% rename from embedded_licenses/github.com/shurcooL/sanitized_anchor_name/LICENSE rename to src/embedded_licenses/github.com/shurcooL/sanitized_anchor_name/LICENSE diff --git a/embedded_licenses/github.com/sirupsen/logrus/LICENSE b/src/embedded_licenses/github.com/sirupsen/logrus/LICENSE similarity index 100% rename from embedded_licenses/github.com/sirupsen/logrus/LICENSE rename to src/embedded_licenses/github.com/sirupsen/logrus/LICENSE diff --git a/embedded_licenses/github.com/urfave/cli/v2/LICENSE b/src/embedded_licenses/github.com/urfave/cli/v2/LICENSE similarity index 100% rename from embedded_licenses/github.com/urfave/cli/v2/LICENSE rename to src/embedded_licenses/github.com/urfave/cli/v2/LICENSE diff --git a/embedded_licenses/golang.org/x/crypto/ssh/terminal/LICENSE b/src/embedded_licenses/golang.org/x/crypto/ssh/terminal/LICENSE similarity index 100% rename from embedded_licenses/golang.org/x/crypto/ssh/terminal/LICENSE rename to src/embedded_licenses/golang.org/x/crypto/ssh/terminal/LICENSE diff --git a/embedded_licenses/golang.org/x/sys/unix/LICENSE b/src/embedded_licenses/golang.org/x/sys/unix/LICENSE similarity index 100% rename from embedded_licenses/golang.org/x/sys/unix/LICENSE rename to src/embedded_licenses/golang.org/x/sys/unix/LICENSE diff --git a/pkg/entropy/entropy.go b/src/entropy/entropy.go similarity index 82% rename from pkg/entropy/entropy.go rename to src/entropy/entropy.go index 691b940..3cdbb0a 100644 --- a/pkg/entropy/entropy.go +++ b/src/entropy/entropy.go @@ -5,9 +5,10 @@ import ( "github.com/nbutton23/zxcvbn-go" ) -// Initially I wrote my own entropy calculator but found this package that's based on a Dropbox +// Initially I wrote my own entropy calculator but found this package that's based on a Dropbox package // it's more conservative in its estimation than my original and those I found online. So, it's included here. +// PrintEntropy returns the metadata about the strenght of a given passphrase func PrintEntropy(passphrase string) { entropy := zxcvbn.PasswordStrength(passphrase, nil) fmt.Println("Password: " + entropy.Password) diff --git a/pkg/entropy/entropy_test.go b/src/entropy/entropy_test.go similarity index 100% rename from pkg/entropy/entropy_test.go rename to src/entropy/entropy_test.go diff --git a/pkg/generate/generate.go b/src/generate/generate.go similarity index 76% rename from pkg/generate/generate.go rename to src/generate/generate.go index 6fea1fe..40aff30 100644 --- a/pkg/generate/generate.go +++ b/src/generate/generate.go @@ -1,14 +1,16 @@ package generate import ( - "github.com/gophrase/internal" - "github.com/gophrase/pkg/corpus" + "github.com/jmillerv/gophrase/config" + "github.com/jmillerv/gophrase/corpus" "math/rand" "strconv" "strings" "time" ) +// Functions are exported in this package because they will eventually be imported in other parts of the code. + type Params struct { WordCount int WordList string @@ -17,6 +19,7 @@ type Params struct { Numbers bool } +// Capitals handles adding capitalized letters to a passphrase. // TODO There is a chance this doesn't capitalize. Need to make a validator. func Capitals(passphrase []string) string { rand.Seed(time.Now().UnixNano()) @@ -41,6 +44,7 @@ func choice() int { return opts[rand.Intn(len(opts))] } +// HandleFlags looks at the parameters and updates the passphrase based on the flags func HandleFlags(p *Params, passphrase []string) string { var returnValue string if p.SpecialChars == true { @@ -68,14 +72,16 @@ func key(wordList string) int { return key } +// keySize determines the size of the key for random generation based on the wordlist used. func keySize(wordList string) int { - if wordList == internal.EFF_SHORT_1 || wordList == internal.EFF_SHORT_2 { + if wordList == config.EffShort1 || wordList == config.EffShort2 { return 4 } else { return 5 } } +// Password generates a password func Password(p *Params) string { var passphrase []string for i := 1; i <= p.WordCount; i++ { @@ -90,18 +96,21 @@ func Password(p *Params) string { return returnValue } +// SpecialCharacters handles adding special characters to the passphrase func SpecialCharacters(passphrase []string) []string { rand.Seed(time.Now().UnixNano()) passphrase = append(passphrase, "") - charCount := rand.Intn(len(passphrase)) + 1 + charCount := rand.Intn(len(passphrase)) + 1 // add a random number of special characters for i := 0; i < charCount; i++ { char := corpus.GetSpecialChar() passphrase = append(passphrase, char) } + // shuffle the special characters so they aren't just at the end of a string array rand.Shuffle(len(passphrase), func(i, j int) { passphrase[i], passphrase[j] = passphrase[j], passphrase[i] }) return passphrase } +// Numbers handles adding numbers to the passphrase. func Numbers(passphrase []string) []string { rand.Seed(time.Now().UnixNano()) charCount := rand.Intn(len(passphrase)) + 1 diff --git a/pkg/generate/generate_test.go b/src/generate/generate_test.go similarity index 98% rename from pkg/generate/generate_test.go rename to src/generate/generate_test.go index 2e4c73c..1b6040d 100644 --- a/pkg/generate/generate_test.go +++ b/src/generate/generate_test.go @@ -1,7 +1,7 @@ package generate import ( - "github.com/gophrase/pkg/corpus" + "github.com/jmillerv/gophrase/corpus" "math" "regexp" "strings" diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 0000000..6362434 --- /dev/null +++ b/src/go.mod @@ -0,0 +1,11 @@ +module github.com/jmillerv/gophrase + +go 1.18 + +require ( + github.com/jmillerv/go-utilities v0.0.0-20220606212806-2039fdaf4823 + github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/urfave/cli/v2 v2.1.1 + gopkg.in/yaml.v3 v3.0.1 +) diff --git a/go.sum b/src/go.sum similarity index 93% rename from go.sum rename to src/go.sum index 07f8fa0..9b14d0f 100644 --- a/go.sum +++ b/src/go.sum @@ -23,6 +23,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -49,20 +50,21 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmillerv/go-utilities v0.0.0-20220606212806-2039fdaf4823 h1:JOA81tckQ0Ep/P6iE0oHuXbtL25MCf8gD4sz3NwsWgc= +github.com/jmillerv/go-utilities v0.0.0-20220606212806-2039fdaf4823/go.mod h1:okN4LUTlx7FrTlYcVKXZs059xgpOldGWZupW2MeJXuE= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.15.3 h1:0a2pXOgtB16CqIqXTiT7+K9L73f74n/aNQUnH6Ortew= github.com/karrick/godirwalk v1.15.3/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= @@ -101,6 +103,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -116,6 +120,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= @@ -157,13 +162,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200308013534-11ec41452d41 h1:9Di9iYgOt9ThCipBxChBVhgNipDoE5mxO84rQV7D0FE= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -174,7 +180,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -182,4 +187,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..c24b746 --- /dev/null +++ b/src/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "embed" + _ "embed" + "github.com/jmillerv/gophrase/command" + "github.com/jmillerv/gophrase/config" + "github.com/urfave/cli/v2" + "log" + "os" +) + +// App information constants +const ( + AppName = "Go Phrase" + AppUsage = "CLI for generating secure, memorable passwords" + AppVersion = "v2.0.0 | release: 8.14.22" + AppUsageText = "gophrase gen [word count] [word list] [--flags]" +) + +//go:embed assets/* +var staticFS embed.FS + +func main() { + config.Assets = staticFS + app := *cli.NewApp() + app.Name = AppName + app.Usage = AppUsage + app.UsageText = AppUsageText + app.Version = AppVersion + app.HideHelp = false + app.HideVersion = false + app.Commands = command.Commands + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } +}