20 Commits

Author SHA1 Message Date
max aad2144e7c Build updated binaries 2024-11-01 14:31:08 -05:00
max a1c8d6e531 Bump version 2024-11-01 14:30:16 -05:00
max 0d5d7503ec Build with Go 1.23.2 2024-11-01 14:29:11 -05:00
max ee1a0fedcc Build with Go 1.22 2024-02-14 13:39:33 -06:00
max 3fc3f35bb5 Bump version to 1.3.2 2024-02-14 13:32:56 -06:00
max 9a98788476 Update Go version to 1.22 2024-02-14 13:32:07 -06:00
Maximilian 43b8d3b618 Update binaries to 1.3.1 2023-02-14 16:33:07 -06:00
Maximilian 6d1e700d8b Update version 2023-02-14 16:12:15 -06:00
Maximilian 1b2fcd72b9 Use switch statements for argument matching, use a map for removing disallowedCharacters, and set up worker pool for concurrent "chunk" generation of the password 2023-02-14 16:12:02 -06:00
Maximilian 6c20c7bb8b Add go.sum 2023-02-14 15:27:38 -06:00
Maximilian f5289baecd Update Go version to 1.20 2023-02-14 15:27:24 -06:00
max bb4dda5d9f Add new release binaries for 1.3.0 2023-02-07 08:21:16 -06:00
max 14b7b1d181 Update README.md 2023-02-07 08:16:09 -06:00
max 83c7065d2a Full refactor, remove dead code, remove math/rand, add version arg, remove symbol arg, help arg, and improve remove disallowed character argument 2023-02-07 08:06:22 -06:00
max 3978c9ad47 Preemptively add building support (for version 1.3.0) for freebsd (386, amd64, and arm), plan9 (386, amd64, and arm), and Linux/Windows arm 2023-02-03 17:55:43 -06:00
Maximilian e1ced3f76d Update binaries to the latest version 2023-01-30 00:06:15 -06:00
Maximilian cdbca3b074 Add makefile 2023-01-30 00:05:53 -06:00
Maximilian e4eca321f6 Update version 2023-01-29 23:37:46 -06:00
Maximilian 0eacc92a45 Formatting 2023-01-29 23:36:47 -06:00
Maximilian e96fded8ff Cryptographically generate password characters 2023-01-29 23:30:21 -06:00
23 changed files with 202 additions and 50 deletions
+7 -5
View File
@@ -1,20 +1,22 @@
# GoPass
An easy to use command-line password generator that creates secure passwords (Version 1.1 adds proper cryptographic
seeding of math/rand)
An easy to use command-line password generator that creates secure passwords
# Usage:
`./gopass [number of characters]`<br>
or <br>
`./gopass [number of characters] "[excluded characters]"`
`./gopass [number of characters] -r=[excluded characters] [-s to remove all symbols]`
<hr>
eg: `./gopass 32` <br>
output: `E$bGOiiPASS*,ISl{!MJ&<\[COOL0eVw` <br>
eg (with excluded characters): `./gopass 32 "$,!"` <br>
output: `EYbGOiiPASS*2ISl{?MJ&<\[COOL0eVw` <- note the excluded characters are not present in the output
eg: (with excluded characters): `./gopass 32 -r=$,!` <br>
output: `EYbGOiiPASS*2ISl{?MJ&<\[COOL0eVw` <- note the excluded characters are not present in the output <br>
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:
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1,3 +1,3 @@
module GoPass
go 1.19
go 1.23.2
View File
+107 -44
View File
@@ -1,68 +1,131 @@
// GoPass
// Author: Maximilian Patterson
// Version: 1.2.1
package main
import (
cryptorand "crypto/rand"
"encoding/binary"
"crypto/rand"
"fmt"
mathrand "math/rand"
"math/big"
"os"
"runtime"
"strconv"
"strings"
)
var allowedCharacters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`~!@#$%^&*()_+[]\\{}|;':,./<>?")
func main() {
// Take in all OS arg
args := os.Args[1:]
if len(args) < 1 {
println("No password length specified! (ex: ./gopass 16)")
return
const (
Version = "1.3.1"
symbols = "`~!@#$%^&*()_+[]\\{}|;':,./<>?"
chunkSize = 16 // The size of each chunk of the password to be generated by the worker goroutines
)
func matchArguments(args []string) string {
// If there are no arguments
if len(args) == 0 {
return "No password length specified! (ex: gopass 16)"
}
// Convert String arg to int
size, err := strconv.Atoi(args[0])
if err != nil {
println("First argument supplied must be an integer! (ex: 16)")
return
}
// Grab second argument (if it exists) and use it as a disallowed character(s)
var disallowed []rune
if len(args) == 2 {
// Break apart the string into a slice of runes
disallowed = []rune(args[1])
// Remove all disallowed characters from the allowedCharacters slice
for _, r := range disallowed {
for i, v := range allowedCharacters {
if v == r {
allowedCharacters = append(allowedCharacters[:i], allowedCharacters[i+1:]...)
}
}
// First argument is special, must be an integer, -v, or -h
var size = 0 // Password length
switch args[0] {
case "-v":
return "GoPass version " + Version
case "-h":
return "GoPass - A simple password generator written in Go\n" +
"Usage: gopass [length] [disallowed characters] [optional remove symbols -s]\n" +
" Example: gopass 16\n" +
" Example: gopass 16 -r=abc123!@#\n" +
" Example: gopass 16 -s\n" +
"\nFor help (this output): gopass -h\n" +
"For version: gopass -v\n"
default:
err := error(nil)
size, err = strconv.Atoi(args[0])
if err != nil {
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
pass := make([]rune, size)
// Seed rand with time
var b [8]byte
_, err = cryptorand.Read(b[:])
if err != nil {
println("Error securely seeding crypto/rand!")
return
}
mathrand.Seed(int64(binary.LittleEndian.Uint64(b[:])))
// Create a channel to receive chunks of the password
passChan := make(chan []rune)
// Assign every slot of pass to a random allowedCharacter
for i := range pass {
// Generate a random int greater than 0 and not to exceed the length of allowedCharacters
pass[i] = allowedCharacters[mathrand.Intn(len(allowedCharacters))]
// Determine the number of worker goroutines to use
numWorkers := runtime.NumCPU()
// Launch the worker goroutines
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
}
}()
}
// Print the password
fmt.Println(string(pass))
// Collect the chunks of the password from the channel
for i := 0; i < size; i += chunkSize {
chunk := <-passChan
copy(pass[i:], chunk)
}
return string(pass)
}
func main() {
// Process arguments
fmt.Println(matchArguments(os.Args[1:]))
}
+87
View File
@@ -0,0 +1,87 @@
# The current version number of the program
VERSION := 1.3.3
# 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