Compare commits

..

No commits in common. "master" and "v1.2.0" have entirely different histories.

23 changed files with 47 additions and 202 deletions

View File

@ -1,22 +1,20 @@
# GoPass # GoPass
An easy to use command-line password generator that creates secure passwords An easy to use command-line password generator that creates secure passwords (Version 1.1 adds proper cryptographic
seeding of math/rand)
# Usage: # Usage:
`./gopass [number of characters]`<br> `./gopass [number of characters]`<br>
or <br> or <br>
`./gopass [number of characters] -r=[excluded characters] [-s to remove all symbols]` `./gopass [number of characters] "[excluded characters]"`
<hr> <hr>
eg: `./gopass 32` <br> eg: `./gopass 32` <br>
output: `E$bGOiiPASS*,ISl{!MJ&<\[COOL0eVw` <br> output: `E$bGOiiPASS*,ISl{!MJ&<\[COOL0eVw` <br>
eg: (with excluded characters): `./gopass 32 -r=$,!` <br> eg (with excluded characters): `./gopass 32 "$,!"` <br>
output: `EYbGOiiPASS*2ISl{?MJ&<\[COOL0eVw` <- note the excluded characters are not present in the output <br> output: `EYbGOiiPASS*2ISl{?MJ&<\[COOL0eVw` <- note the excluded characters are not present in the output
eg: `./gopass 32 -s` <br>
output: `LEYbGOiiPASS2ISlMJCOOL0eRt3KPOVw` <- note the symbols are not present in the output <br>
eg: `./gopass 32 -r=$,! -s` the -r and -s flags can be combined <br>
# How to install/use for Windows: # How to install/use for Windows:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/gopass-linux-386-v1.2.0 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
go.mod
View File

@ -1,3 +1,3 @@
module GoPass module GoPass
go 1.20 go 1.19

0
go.sum
View File

148
main.go
View File

@ -1,131 +1,65 @@
// GoPass // GoPass
// Author: Maximilian Patterson // Author: Maximilian Patterson
// Version: 1.2.0
package main package main
import ( import (
"crypto/rand" cryptorand "crypto/rand"
"encoding/binary"
"fmt" "fmt"
"math/big" mathrand "math/rand"
"os" "os"
"runtime"
"strconv" "strconv"
"strings"
) )
var allowedCharacters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`~!@#$%^&*()_+[]\\{}|;':,./<>?") var allowedCharacters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`~!@#$%^&*()_+[]\\{}|;':,./<>?")
const ( func main() {
Version = "1.3.1" // Take in all OS arg
symbols = "`~!@#$%^&*()_+[]\\{}|;':,./<>?" args := os.Args[1:]
chunkSize = 16 // The size of each chunk of the password to be generated by the worker goroutines if len(args) < 1 {
) panic("No password length specified! (ex: ./gopass 16)")
func matchArguments(args []string) string {
// If there are no arguments
if len(args) == 0 {
return "No password length specified! (ex: gopass 16)"
} }
// First argument is special, must be an integer, -v, or -h // Convert String arg to int
var size = 0 // Password length size, err := strconv.Atoi(args[0])
switch args[0] { if err != nil {
case "-v": panic("First argument supplied must be an integer! (ex: 16)")
return "GoPass version " + Version }
case "-h":
return "GoPass - A simple password generator written in Go\n" + // Grab second argument (if it exists) and use it as a disallowed character(s)
"Usage: gopass [length] [disallowed characters] [optional remove symbols -s]\n" + var disallowed []rune
" Example: gopass 16\n" + if len(args) == 2 {
" Example: gopass 16 -r=abc123!@#\n" + // Break apart the string into a slice of runes
" Example: gopass 16 -s\n" + disallowed = []rune(args[1])
"\nFor help (this output): gopass -h\n" +
"For version: gopass -v\n" // Remove all disallowed characters from the allowedCharacters slice
default: for _, r := range disallowed {
err := error(nil) for i, v := range allowedCharacters {
size, err = strconv.Atoi(args[0]) if v == r {
if err != nil { allowedCharacters = append(allowedCharacters[:i], allowedCharacters[i+1:]...)
return "Invalid first argument (\"" + args[0] + "\") supplied! (Type gopass -h for help)" }
}
} }
} }
for i := 1; i < len(args); i++ {
v := args[i]
switch {
case v == "-s":
removeDisallowed([]rune(symbols))
case strings.HasPrefix(v, "-r="):
// Remove all characters after the = until next whitespace
removeDisallowed([]rune(v[2:]))
default:
return "Invalid argument (\"" + v + "\") supplied! (Type gopass -h for help)"
}
}
if size <= 0 {
return "No/invalid password length specified! (ex: gopass 16)"
} else {
return generatePassword(size)
}
}
// Remove all disallowed characters from the allowedCharacters slice
func removeDisallowed(disallowed []rune) {
disallowedMap := make(map[rune]bool, len(disallowed))
for _, r := range disallowed {
disallowedMap[r] = true
}
i := 0
for _, v := range allowedCharacters {
if !disallowedMap[v] {
allowedCharacters[i] = v
i++
}
}
allowedCharacters = allowedCharacters[:i]
}
func generatePassword(size int) string {
// Make empty array of runes with size of size // Make empty array of runes with size of size
pass := make([]rune, size) pass := make([]rune, size)
// Create a channel to receive chunks of the password // Seed rand with time
passChan := make(chan []rune) var b [8]byte
_, err = cryptorand.Read(b[:])
if err != nil {
panic("Error securely seeding crypto/rand!")
}
mathrand.Seed(int64(binary.LittleEndian.Uint64(b[:])))
// Determine the number of worker goroutines to use // Assign every slot of pass to a random allowedCharacter
numWorkers := runtime.NumCPU() for i := range pass {
// Generate a random int greater than 0 and not to exceed the length of allowedCharacters
// Launch the worker goroutines pass[i] = allowedCharacters[mathrand.Intn(len(allowedCharacters))]
for i := 0; i < numWorkers; i++ {
go func() {
allowedLen := len(allowedCharacters)
for {
// Generate a chunk of the password
chunk := make([]rune, chunkSize)
for i := range chunk {
index, err := rand.Int(rand.Reader, big.NewInt(int64(allowedLen)))
if err != nil {
println("Error securely generating random character chunk!")
return
}
chunk[i] = allowedCharacters[index.Int64()]
}
// Send the chunk of the password to the main goroutine
passChan <- chunk
}
}()
} }
// Collect the chunks of the password from the channel // Print the password
for i := 0; i < size; i += chunkSize { fmt.Println(string(pass))
chunk := <-passChan
copy(pass[i:], chunk)
}
return string(pass)
}
func main() {
// Process arguments
fmt.Println(matchArguments(os.Args[1:]))
} }

View File

@ -1,87 +0,0 @@
# The current version number of the program
VERSION := 1.3.1
# List of OS and architecture combinations to build
BUILD_OS_ARCH := \
darwin/amd64 \
freebsd/386 \
freebsd/amd64 \
freebsd/arm \
linux/386 \
linux/amd64 \
linux/arm \
plan9/386 \
plan9/amd64 \
plan9/arm \
windows/386 \
windows/amd64 \
windows/arm
# Build all targets
all: $(BUILD_OS_ARCH)
# Build targets in the form of `OS/ARCH`
darwin/amd64:
GOOS=darwin \
GOARCH=amd64 \
go build -ldflags="-s -w" -o "gopass-darwin-amd64-$(VERSION)" main.go
freebsd/386:
GOOS=freebsd \
GOARCH=386 \
go build -ldflags="-s -w" -o "gopass-freebsd-386-$(VERSION)" main.go
freebsd/amd64:
GOOS=freebsd \
GOARCH=amd64 \
go build -ldflags="-s -w" -o "gopass-freebsd-amd64-$(VERSION)" main.go
freebsd/arm:
GOOS=freebsd \
GOARCH=arm \
go build -ldflags="-s -w" -o "gopass-freebsd-arm-$(VERSION)" main.go
linux/386:
GOOS=linux \
GOARCH=386 \
go build -ldflags="-s -w" -o "gopass-linux-386-$(VERSION)" main.go
linux/amd64:
GOOS=linux \
GOARCH=amd64 \
go build -ldflags="-s -w" -o "gopass-linux-amd64-$(VERSION)" main.go
linux/arm:
GOOS=linux \
GOARCH=arm \
go build -ldflags="-s -w" -o "gopass-linux-arm-$(VERSION)" main.go
plan9/386:
GOOS=plan9 \
GOARCH=386 \
go build -ldflags="-s -w" -o "gopass-plan9-386-$(VERSION)" main.go
plan9/amd64:
GOOS=plan9 \
GOARCH=amd64 \
go build -ldflags="-s -w" -o "gopass-plan9-amd64-$(VERSION)" main.go
plan9/arm:
GOOS=plan9 \
GOARCH=arm \
go build -ldflags="-s -w" -o "gopass-plan9-arm-$(VERSION)" main.go
windows/386:
GOOS=windows \
GOARCH=386 \
go build -ldflags="-s -w" -o "gopass-windows-386-$(VERSION)" main.go
windows/amd64:
GOOS=windows \
GOARCH=amd64 \
go build -ldflags="-s -w" -o "gopass-windows-amd64-$(VERSION)" main.go
windows/arm:
GOOS=windows \
GOARCH=arm \
go build -ldflags="-s -w" -o "gopass-windows-arm-$(VERSION)" main.go