mirror of
https://github.com/wneessen/apg-go.git
synced 2024-12-23 03:30:39 +01:00
Added spelling of pws. Ready for v0.2.4
This commit is contained in:
parent
eb221ccc69
commit
8b9269b1b9
4 changed files with 258 additions and 38 deletions
23
apg.go
23
apg.go
|
@ -30,8 +30,10 @@ type cliOpts struct {
|
|||
humanReadable bool
|
||||
excludeChars string
|
||||
newStyleModes string
|
||||
spellPassword bool
|
||||
showHelp bool
|
||||
showVersion bool
|
||||
outputMode int
|
||||
}
|
||||
|
||||
var config cliOpts
|
||||
|
@ -43,7 +45,8 @@ func init() {
|
|||
flag.BoolVar(&config.useUpperCase, "U", false, "Use upper case characters in passwords")
|
||||
flag.BoolVar(&config.useNumber, "N", false, "Use numbers in passwords")
|
||||
flag.BoolVar(&config.useSpecial, "S", false, "Use special characters in passwords")
|
||||
flag.BoolVar(&config.useComplex, "C", true, "Generate complex passwords (implies -L -U -N -S, disables -H)")
|
||||
flag.BoolVar(&config.useComplex, "C", false, "Generate complex passwords (implies -L -U -N -S, disables -H)")
|
||||
flag.BoolVar(&config.spellPassword, "l", false, "Spell generated password")
|
||||
flag.BoolVar(&config.humanReadable, "H", false, "Generate human-readable passwords")
|
||||
flag.BoolVar(&config.showVersion, "v", false, "Show version")
|
||||
|
||||
|
@ -76,6 +79,22 @@ func main() {
|
|||
fmt.Printf("getRandChar returned an error: %q\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(pwString)
|
||||
|
||||
switch config.outputMode {
|
||||
case 1:
|
||||
{
|
||||
spelledPw, err := spellPasswordString(pwString)
|
||||
if err != nil {
|
||||
fmt.Printf("spellPasswordString returned an error: %q\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%v (%v)\n", pwString, spelledPw)
|
||||
}
|
||||
default:
|
||||
{
|
||||
fmt.Println(pwString)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
81
apg_test.go
81
apg_test.go
|
@ -207,6 +207,72 @@ func TestGetCharRange(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
// Test Conversions
|
||||
func TestConvert(t *testing.T) {
|
||||
t.Run("convert_A_to_Alfa", func(t *testing.T) {
|
||||
charToString, err := convertCharToName('A')
|
||||
if err != nil {
|
||||
t.Errorf("Character to string conversion failed: %v", err.Error())
|
||||
}
|
||||
if charToString != "Alfa" {
|
||||
t.Errorf("Converting 'A' to string did not return the correct value of 'Alfa': %q", charToString)
|
||||
}
|
||||
})
|
||||
t.Run("convert_a_to_alfa", func(t *testing.T) {
|
||||
charToString, err := convertCharToName('a')
|
||||
if err != nil {
|
||||
t.Errorf("Character to string conversion failed: %v", err.Error())
|
||||
}
|
||||
if charToString != "alfa" {
|
||||
t.Errorf("Converting 'a' to string did not return the correct value of 'alfa': %q", charToString)
|
||||
}
|
||||
})
|
||||
t.Run("convert_0_to_ZERO", func(t *testing.T) {
|
||||
charToString, err := convertCharToName('0')
|
||||
if err != nil {
|
||||
t.Errorf("Character to string conversion failed: %v", err.Error())
|
||||
}
|
||||
if charToString != "ZERO" {
|
||||
t.Errorf("Converting '0' to string did not return the correct value of 'ZERO': %q", charToString)
|
||||
}
|
||||
})
|
||||
t.Run("convert_/_to_SLASH", func(t *testing.T) {
|
||||
charToString, err := convertCharToName('/')
|
||||
if err != nil {
|
||||
t.Errorf("Character to string conversion failed: %v", err.Error())
|
||||
}
|
||||
if charToString != "SLASH" {
|
||||
t.Errorf("Converting '/' to string did not return the correct value of 'SLASH': %q", charToString)
|
||||
}
|
||||
})
|
||||
t.Run("all_chars_convert_to_string", func(t *testing.T) {
|
||||
config.useUpperCase = true
|
||||
config.useLowerCase = true
|
||||
config.useNumber = true
|
||||
config.useSpecial = true
|
||||
config.humanReadable = false
|
||||
charRange := getCharRange()
|
||||
for _, curChar := range charRange {
|
||||
_, err := convertCharToName(byte(curChar))
|
||||
if err != nil {
|
||||
t.Errorf("Character to string conversion failed: %v", err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("spell_Ab!_to_strings", func(t *testing.T) {
|
||||
pwString := "Ab!"
|
||||
spelledString, err := spellPasswordString(pwString)
|
||||
if err != nil {
|
||||
t.Errorf("password spelling failed: %v", err.Error())
|
||||
}
|
||||
if spelledString != "Alfa/bravo/EXCLAMATION_POINT" {
|
||||
t.Errorf(
|
||||
"Spelling pwString 'Ab!' is expected to provide 'Alfa/bravo/EXCLAMATION_POINT', but returned: %q",
|
||||
spelledString)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Forced failures
|
||||
func TestForceFailures(t *testing.T) {
|
||||
t.Run("too_big_big.NewInt_value", func(t *testing.T) {
|
||||
|
@ -241,6 +307,21 @@ func BenchmarkGetRandChar(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
// Benchmark: Random char generation
|
||||
func BenchmarkConvertChar(b *testing.B) {
|
||||
config.useUpperCase = true
|
||||
config.useLowerCase = true
|
||||
config.useNumber = true
|
||||
config.useSpecial = true
|
||||
config.humanReadable = false
|
||||
charRange := getCharRange()
|
||||
for i := 0; i < b.N; i++ {
|
||||
charToConv, _ := getRandChar(&charRange, 1)
|
||||
charBytes := []byte(charToConv)
|
||||
_, _ = convertCharToName(charBytes[0])
|
||||
}
|
||||
}
|
||||
|
||||
// Contains function to search a given slice for values
|
||||
func containsByte(allowedBytes []int, currentChar int) bool {
|
||||
for _, charInt := range allowedBytes {
|
||||
|
|
110
convert.go
Normal file
110
convert.go
Normal file
|
@ -0,0 +1,110 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
symbNumNames = map[byte]string{
|
||||
'1': "ONE",
|
||||
'2': "TWO",
|
||||
'3': "THREE",
|
||||
'4': "FOUR",
|
||||
'5': "FIVE",
|
||||
'6': "SIX",
|
||||
'7': "SEVEN",
|
||||
'8': "EIGHT",
|
||||
'9': "NINE",
|
||||
'0': "ZERO",
|
||||
33: "EXCLAMATION_POINT",
|
||||
34: "QUOTATION_MARK",
|
||||
35: "CROSSHATCH",
|
||||
36: "DOLLAR_SIGN",
|
||||
37: "PERCENT_SIGN",
|
||||
38: "AMPERSAND",
|
||||
39: "APOSTROPHE",
|
||||
40: "LEFT_PARENTHESIS",
|
||||
41: "RIGHT_PARENTHESIS",
|
||||
42: "ASTERISK",
|
||||
43: "PLUS_SIGN",
|
||||
44: "COMMA",
|
||||
45: "HYPHEN",
|
||||
46: "PERIOD",
|
||||
47: "SLASH",
|
||||
58: "COLON",
|
||||
59: "SEMICOLON",
|
||||
60: "LESS_THAN",
|
||||
61: "EQUAL_SIGN",
|
||||
62: "GREATER_THAN",
|
||||
63: "QUESTION_MARK",
|
||||
64: "AT_SIGN",
|
||||
91: "LEFT_BRACKET",
|
||||
92: "BACKSLASH",
|
||||
93: "RIGHT_BRACKET",
|
||||
94: "CIRCUMFLEX",
|
||||
95: "UNDERSCORE",
|
||||
96: "GRAVE",
|
||||
123: "LEFT_BRACE",
|
||||
124: "VERTICAL_BAR",
|
||||
125: "RIGHT_BRACE",
|
||||
126: "TILDE",
|
||||
}
|
||||
alphabetNames = map[byte]string{
|
||||
'A': "Alfa",
|
||||
'B': "Bravo",
|
||||
'C': "Charlie",
|
||||
'D': "Delta",
|
||||
'E': "Echo",
|
||||
'F': "Foxtrot",
|
||||
'G': "Golf",
|
||||
'H': "Hotel",
|
||||
'I': "India",
|
||||
'J': "Juliett",
|
||||
'K': "Kilo",
|
||||
'L': "Lima",
|
||||
'M': "Mike",
|
||||
'N': "November",
|
||||
'O': "Oscar",
|
||||
'P': "Papa",
|
||||
'Q': "Quebec",
|
||||
'R': "Romeo",
|
||||
'S': "Sierra",
|
||||
'T': "Tango",
|
||||
'U': "Uniform",
|
||||
'V': "Victor",
|
||||
'W': "Whiskey",
|
||||
'X': "X_ray",
|
||||
'Y': "Yankee",
|
||||
'Z': "Zulu",
|
||||
}
|
||||
)
|
||||
|
||||
func spellPasswordString(pwString string) (string, error) {
|
||||
var returnString []string
|
||||
for _, curChar := range pwString {
|
||||
curSpellString, err := convertCharToName(byte(curChar))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
returnString = append(returnString, curSpellString)
|
||||
}
|
||||
return strings.Join(returnString, "/"), nil
|
||||
}
|
||||
|
||||
func convertCharToName(charByte byte) (string, error) {
|
||||
var returnString string
|
||||
if charByte > 64 && charByte < 91 {
|
||||
returnString = alphabetNames[charByte]
|
||||
} else if charByte > 96 && charByte < 123 {
|
||||
returnString = strings.ToLower(alphabetNames[charByte-32])
|
||||
} else {
|
||||
returnString = symbNumNames[charByte]
|
||||
}
|
||||
|
||||
if returnString == "" {
|
||||
err := fmt.Errorf("cannot convert to character to name: %q is an unknown character", charByte)
|
||||
return "", err
|
||||
}
|
||||
return returnString, nil
|
||||
}
|
82
params.go
82
params.go
|
@ -5,8 +5,52 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
// Parse the parameters and set the according config flags
|
||||
func parseParams() {
|
||||
parseNewStyleParams()
|
||||
|
||||
// Complex overrides everything
|
||||
if config.useComplex {
|
||||
config.useUpperCase = true
|
||||
config.useLowerCase = true
|
||||
config.useSpecial = true
|
||||
config.useNumber = true
|
||||
config.humanReadable = false
|
||||
}
|
||||
|
||||
if config.useUpperCase == false &&
|
||||
config.useLowerCase == false &&
|
||||
config.useNumber == false &&
|
||||
config.useSpecial == false {
|
||||
fmt.Printf("No password mode set. Cannot generate password from empty character set.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set output mode
|
||||
if config.spellPassword {
|
||||
config.outputMode = 1
|
||||
}
|
||||
}
|
||||
|
||||
// Get the password length from the given cli flags
|
||||
func getPwLengthFromParams() int {
|
||||
pwLength := config.minPassLen
|
||||
if pwLength < config.minPassLen {
|
||||
pwLength = config.minPassLen
|
||||
}
|
||||
if pwLength > config.maxPassLen {
|
||||
pwLength = config.maxPassLen
|
||||
}
|
||||
|
||||
return pwLength
|
||||
}
|
||||
|
||||
// Parse the new style parameters
|
||||
func parseNewStyleParams() {
|
||||
if config.newStyleModes == "" {
|
||||
return
|
||||
}
|
||||
|
||||
for _, curParam := range config.newStyleModes {
|
||||
switch curParam {
|
||||
case 'S':
|
||||
|
@ -39,12 +83,11 @@ func parseNewStyleParams() {
|
|||
case 'h':
|
||||
config.humanReadable = false
|
||||
break
|
||||
// APG compatbilitly
|
||||
case 'C':
|
||||
config.useUpperCase = true
|
||||
config.useComplex = true
|
||||
break
|
||||
case 'c':
|
||||
config.useUpperCase = false
|
||||
config.useComplex = false
|
||||
break
|
||||
default:
|
||||
fmt.Printf("Unknown password style parameter: %q\n", string(curParam))
|
||||
|
@ -52,36 +95,3 @@ func parseNewStyleParams() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getPwLengthFromParams() int {
|
||||
pwLength := config.minPassLen
|
||||
if pwLength < config.minPassLen {
|
||||
pwLength = config.minPassLen
|
||||
}
|
||||
if pwLength > config.maxPassLen {
|
||||
pwLength = config.maxPassLen
|
||||
}
|
||||
|
||||
return pwLength
|
||||
}
|
||||
|
||||
func parseParams() {
|
||||
if config.useComplex {
|
||||
config.useUpperCase = true
|
||||
config.useLowerCase = true
|
||||
config.useSpecial = true
|
||||
config.useNumber = true
|
||||
config.humanReadable = false
|
||||
}
|
||||
if config.newStyleModes != "" {
|
||||
parseNewStyleParams()
|
||||
}
|
||||
|
||||
if config.useUpperCase == false &&
|
||||
config.useLowerCase == false &&
|
||||
config.useNumber == false &&
|
||||
config.useSpecial == false {
|
||||
fmt.Printf("No password mode set. Cannot generate password from empty character set.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue