From 0e80f704bc2f6e10d8c3b6db22bbf191436b01a5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg Date: Tue, 16 Jul 2019 22:56:17 +0200 Subject: [PATCH] feat: generate a random password --- CHANGELOG.md | 5 +++++ README.md | 1 + gpm/cli.go | 38 ++++++++++++++++++++++++++++++++++++-- gpm/config.go | 14 +++++++++++--- gpm/main.go | 11 ++++++++++- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3d6107..235f5ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ Which is based on [Keep A Changelog](http://keepachangelog.com/) ## Unreleased +### Added + +- Use go module to get this software +- Generate random password + ## v1.0.0 - 2019-07-12 ### Added diff --git a/README.md b/README.md index 4a50408..3a266a7 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ gpm is passwords manager write in go and use AES-256 to encrypt the wallets - generate OTP code - copy your login, password or otp in clipboard - manage multiple wallets +- generate random password ## Install diff --git a/gpm/cli.go b/gpm/cli.go index 062dce3..36a35c6 100644 --- a/gpm/cli.go +++ b/gpm/cli.go @@ -17,6 +17,7 @@ package gpm import( "bufio" "fmt" + "math/rand" "os" "strconv" "syscall" @@ -65,6 +66,29 @@ func (c *Cli) printEntries(entries []Entry) { } } +// generate a random password +func (c *Cli) generatePassword(length int, letter bool, digit bool, special bool) string { + digits := "0123456789" + specials := "~=+%^*/()[]{}/!@#$?|" + letters := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + chars := "" + password := make([]byte, length) + + if letter { chars = chars + letters } + if digit { chars = chars + digits } + if special { chars = chars + specials } + if !letter && !digit && !special { + chars = digits + letters + } + + rand.Seed(time.Now().UnixNano()) + for i := 0; i < length; i++ { + password[i] = chars[rand.Intn(len(chars))] + } + + return string(password) +} + // error print a message and exit) func (c *Cli) error(msg string) { fmt.Println(msg) @@ -190,7 +214,12 @@ func (c *Cli) addEntry() { entry.Group = c.input("Enter the group: ", "", true) entry.URI = c.input("Enter the URI: ", "", true) entry.User = c.input("Enter the username: ", "", true) - entry.Password = c.input("Enter the password: ", "", false) + if *RANDOM { + entry.Password = c.generatePassword(c.Config.PasswordLength, + c.Config.PasswordLetter, c.Config.PasswordDigit, c.Config.PasswordSpecial) + } else { + entry.Password = c.input("Enter the new password: ", entry.Password, false) + } entry.OTP = c.input("Enter the OTP key: ", "", false) entry.Comment = c.input("Enter a comment: ", "", true) @@ -210,7 +239,12 @@ func (c *Cli) updateEntry() { entry.Group = c.input("Enter the new group: ", entry.Group, true) entry.URI = c.input("Enter the new URI: ", entry.URI, true) entry.User = c.input("Enter the new username: ", entry.User, true) - entry.Password = c.input("Enter the new password: ", entry.Password, false) + if *RANDOM { + entry.Password = c.generatePassword(c.Config.PasswordLength, + c.Config.PasswordLetter, c.Config.PasswordDigit, c.Config.PasswordSpecial) + } else { + entry.Password = c.input("Enter the new password: ", entry.Password, false) + } entry.OTP = c.input("Enter the new OTP key: ", entry.OTP, false) entry.Comment = c.input("Enter a new comment: ", entry.Comment, true) diff --git a/gpm/config.go b/gpm/config.go index 75597bd..441fc84 100644 --- a/gpm/config.go +++ b/gpm/config.go @@ -25,8 +25,12 @@ import ( // Config struct contain the config type Config struct { - WalletDir string `json:"wallet_dir"` - WalletDefault string `json:"wallet_default"` + WalletDir string `json:"wallet_dir"` + WalletDefault string `json:"wallet_default"` + PasswordLength int `json:"password_length"` + PasswordLetter bool `json:"password_letter"` + PasswordDigit bool `json:"password_digit"` + PasswordSpecial bool `json:"password_special"` } // Init the configuration @@ -43,7 +47,11 @@ func (c *Config) Init() error { } else { c.WalletDir = fmt.Sprintf("%s/.config/mpw", user.HomeDir) } - c.WalletDefault = "default" + c.WalletDefault = "default" + c.PasswordLength = 16 + c.PasswordLetter = true + c.PasswordDigit = true + c.PasswordSpecial = false return nil } diff --git a/gpm/main.go b/gpm/main.go index cf02515..5f5dc18 100644 --- a/gpm/main.go +++ b/gpm/main.go @@ -15,6 +15,7 @@ package gpm import( + "fmt" "flag" "os" ) @@ -25,11 +26,17 @@ var( UPDATE = flag.Bool("update", false, "update an entry") DELETE = flag.Bool("delete", false, "delete an entry") LIST = flag.Bool("list", false, "list the entries in a wallet") + LENGTH = flag.Int("length", 16, "specify the password length") COPY = flag.Bool("copy", false, "enter an copy mode for an entry") CONFIG = flag.String("config", "", "specify the config file") GROUP = flag.String("group", "", "search the entries in this group ") - PATTERN = flag.String("pattern", "", "search the entries with this pattern") WALLET = flag.String("wallet", "", "specify the wallet") + PATTERN = flag.String("pattern", "", "search the entries with this pattern") + RANDOM = flag.Bool("random", false, "generate a random password for a new entry or an update") + PASSWD = flag.Bool("password", false, "generate and print a random password") + DIGIT = flag.Bool("digit", false, "use digit to generate a random password") + LETTER = flag.Bool("letter", false, "use letter to generate a random password") + SPECIAL = flag.Bool("special", false, "use special chars to generate a random password") HELP = flag.Bool("help", false, "print this help message") ) @@ -42,6 +49,8 @@ func Run() { if *HELP { flag.PrintDefaults() os.Exit(1) + } else if *PASSWD { + fmt.Println(cli.generatePassword(*LENGTH, *LETTER, *DIGIT, *SPECIAL)) } else if *LIST { cli.listEntry() } else if *COPY {