Skip to content

Commit 15418f0

Browse files
authored
Merge pull request #15 from pythonhacker/development
Development -> Release
2 parents 04888ad + e7737de commit 15418f0

File tree

3 files changed

+116
-10
lines changed

3 files changed

+116
-10
lines changed

actions.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func addNewEntry() error {
239239

240240
if len(passwd) == 0 {
241241
fmt.Printf("\nGenerating password ...")
242-
err, passwd = generateRandomPassword(16)
242+
err, passwd = generateStrongPassword()
243243
fmt.Printf("done")
244244
}
245245
// fmt.Printf("Password => %s\n", passwd)
@@ -315,7 +315,7 @@ func editCurrentEntry(idString string) error {
315315

316316
if strings.ToLower(passwd) == "y" {
317317
fmt.Printf("\nGenerating new password ...")
318-
err, passwd = generateRandomPassword(16)
318+
err, passwd = generateStrongPassword()
319319
}
320320
// fmt.Printf("Password => %s\n", passwd)
321321

crypto.go

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import (
1313
"golang.org/x/crypto/pbkdf2"
1414
"io"
1515
"math/big"
16+
"math/rand"
1617
"os"
18+
"time"
1719
"unsafe"
1820

1921
crand "crypto/rand"
@@ -435,10 +437,10 @@ func decryptFileXChachaPoly(encDbPath string, password string) error {
435437
}
436438

437439
// Generate a random password - for adding listings
438-
func generateRandomPassword(length int) (error, string) {
440+
func generatePassword(length int) (error, string) {
439441

440442
var data []byte
441-
const source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?)(/%#!?)="
443+
const source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+_()$#@!~:/%"
442444

443445
data = make([]byte, length)
444446

@@ -453,3 +455,97 @@ func generateRandomPassword(length int) (error, string) {
453455

454456
return nil, string(data)
455457
}
458+
459+
// Generate a "strong" password
460+
// A strong password is defined as,
461+
// A mix of upper and lower case alphabets
462+
// at least one number [0-9]
463+
// at least one upper case alphabet [A-Z]
464+
// at least one punctuation character
465+
// at least length 12
466+
func generateStrongPassword() (error, string) {
467+
468+
var data []byte
469+
var length int
470+
471+
const sourceAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
472+
const sourceLargeAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
473+
const sourceNum = "0123456789"
474+
const sourcePunct = "=+_()$#@!~:/%"
475+
const source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+_()$#@!~:/%"
476+
477+
// Generate in range 12 - 16
478+
rand.Seed(time.Now().UnixNano())
479+
480+
length = rand.Intn(4) + 12
481+
482+
data = make([]byte, length)
483+
484+
var lengthAlpha int
485+
var i, j, k, l int
486+
487+
// Alpha chars is at least length 3-5
488+
lengthAlpha = rand.Intn(2) + 3
489+
490+
for i = 0; i < lengthAlpha; i++ {
491+
num, err := crand.Int(crand.Reader, big.NewInt(int64(len(sourceAlpha))))
492+
if err != nil {
493+
return err, ""
494+
}
495+
496+
data[i] = sourceAlpha[num.Int64()]
497+
}
498+
499+
// Add in numbers 1 or 2
500+
var lengthNum int
501+
502+
lengthNum = rand.Intn(2) + 1
503+
504+
for j = i; j < i+lengthNum; j++ {
505+
num, err := crand.Int(crand.Reader, big.NewInt(int64(len(sourceNum))))
506+
if err != nil {
507+
return err, ""
508+
}
509+
510+
data[j] = sourceNum[num.Int64()]
511+
}
512+
513+
// Add in punctuations 1 or 2
514+
var lengthPunc int
515+
516+
lengthPunc = rand.Intn(2) + 1
517+
518+
for k = j; k < j+lengthPunc; k++ {
519+
num, err := crand.Int(crand.Reader, big.NewInt(int64(len(sourcePunct))))
520+
if err != nil {
521+
return err, ""
522+
}
523+
524+
data[k] = sourcePunct[num.Int64()]
525+
}
526+
527+
// Fill in the rest
528+
var lengthRem int
529+
530+
lengthRem = length - k
531+
532+
if lengthRem > 0 {
533+
for l = k; l < k+lengthRem; l++ {
534+
num, err := crand.Int(crand.Reader, big.NewInt(int64(len(source))))
535+
if err != nil {
536+
return err, ""
537+
}
538+
539+
data[l] = source[num.Int64()]
540+
}
541+
}
542+
543+
// Shuffle a few times
544+
for i = 0; i < 5; i++ {
545+
rand.Shuffle(len(data), func(i, j int) {
546+
data[i], data[j] = data[j], data[i]
547+
})
548+
}
549+
550+
return nil, string(data)
551+
}

main.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"github.com/pythonhacker/argparse"
88
"os"
9-
"strconv"
109
)
1110

1211
const VERSION = 0.3
@@ -20,6 +19,7 @@ AUTHORS
2019
type actionFunc func(string) error
2120
type actionFunc2 func(string) (error, string)
2221
type voidFunc func() error
22+
type voidFunc2 func() (error, string)
2323

2424
// Structure to keep the options data
2525
type CmdOption struct {
@@ -47,13 +47,11 @@ func printVersionInfo() error {
4747
}
4848

4949
// Command-line wrapper to generateRandomPassword
50-
func genPass(length string) (error, string) {
51-
var iLength int
50+
func genPass() (error, string) {
5251
var err error
5352
var passwd string
5453

55-
iLength, _ = strconv.Atoi(length)
56-
err, passwd = generatePassword(iLength)
54+
err, passwd = generateStrongPassword()
5755

5856
if err != nil {
5957
fmt.Printf("Error generating password - \"%s\"\n", err.Error())
@@ -97,6 +95,9 @@ func performAction(optMap map[string]interface{}) {
9795

9896
stringActions2Map := map[string]actionFunc2{
9997
"decrypt": decryptDatabase,
98+
}
99+
100+
flagsActions2Map := map[string]voidFunc2{
100101
"genpass": genPass,
101102
}
102103

@@ -112,6 +113,15 @@ func performAction(optMap map[string]interface{}) {
112113
}
113114
}
114115

116+
// Flag 2 actions
117+
for key, mappedFunc := range flagsActions2Map {
118+
if *optMap[key].(*bool) {
119+
mappedFunc()
120+
flag = true
121+
break
122+
}
123+
}
124+
115125
// One of bool or string actions
116126
for key, mappedFunc := range boolActionsMap {
117127
if *optMap[key].(*bool) {
@@ -164,7 +174,6 @@ func initializeCmdLine(parser *argparse.Parser) map[string]interface{} {
164174
{"E", "edit", "Edit entry by <id>", "<id>", ""},
165175
{"l", "list-entry", "List entry by <id>", "<id>", ""},
166176
{"x", "export", "Export all entries to <filename>", "<filename>", ""},
167-
{"g", "genpass", "Generate password of given <length>", "<length>", ""},
168177
}
169178

170179
for _, opt := range stringOptions {
@@ -176,6 +185,7 @@ func initializeCmdLine(parser *argparse.Parser) map[string]interface{} {
176185
{"A", "add", "Add a new entry", "", ""},
177186
{"p", "path", "Show current database path", "", ""},
178187
{"a", "list-all", "List all entries in current database", "", ""},
188+
{"g", "genpass", "Generate a strong password of length from 8 - 12", "", ""},
179189
{"s", "show", "Show passwords when listing entries", "", ""},
180190
{"c", "copy", "Copy password to clipboard", "", ""},
181191
{"v", "version", "Show version information and exit", "", ""},

0 commit comments

Comments
 (0)