v0.1.0: Initial check-in

This commit is contained in:
Winni Neessen 2021-03-18 23:26:41 +01:00
parent ebdad33364
commit 5d743f70ae
Signed by: wneessen
GPG key ID: 385AC9889632126E
8 changed files with 209 additions and 1 deletions

1
.gitignore vendored
View file

@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
apg
# Test binary, built with `go test -c`
*.test

8
.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

9
.idea/apg.go.iml Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GrazieInspection" enabled="false" level="TYPO" enabled_by_default="false" />
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/apg.go.iml" filepath="$PROJECT_DIR$/.idea/apg.go.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -1,2 +1,30 @@
# apg.go
Advanced Password Generator Clone
_apg.pl_ is a simple APG-like password generator script written in Go. It tries to replicate the functionality of the "[Automated Password Generator](https://web.archive.org/web/20130313042424/http://www.adel.nursat.kz:80/apg)", which hasn't been maintained since 2003. Since more and more Unix distributions are abondoning the tool, I was looking for an alternative. FreeBSD for example recommends "security/makepasswd", which is also written in Perl but requires much more dependency packages and doesn't offer the feature-set/flexibility of APG. Therefore I decided to write my own implementation. As I never used the "pronouncable password" functionality, I left this out in my version.
## Usage
Simply add the execute-flag to the script and run it
```sh
$ chmod +x apg
$ ./apg
```
## Systemwide installation
To be a proper APG replacement, i suggest to install it into a directory in your PATH and symlink it to "apg":
```sh
$ sudo cp apg /usr/local/bin/apg
```
## CLI options
_apg.go_ replicates some of the parameters of the original APG. Some parameters are different though:
- ```-m, --minpasslen <length>```: The minimum length of the password to be generated
- ```-x, --maxpasslen <length>```: The maximum length of the password to be generated
- ```-n, --numofpass <number of passwords>```: The amount of passwords to be generated
- ```-E, --exclude <list of characters>```: Do not use the specified characters in generated passwords
- ```-U, --uppercase```: Use uppercase characters in passwords
- ```-N, --numbers```: Use numeric characters in passwords
- ```-S, --special```: Use special characters in passwords
- ```-H, --human```: Avoid ambiguous characters in passwords (i. e.: 1, l, I, o, O, 0)
- ```-c, --complex```: Generate complex passwords (implies -U -N -S and disables -H)
- ```-h, --help```: Show a CLI help text
- ```-v, --version```: Show the version number

136
apg.go Normal file
View file

@ -0,0 +1,136 @@
package main
import (
"crypto/rand"
"flag"
"fmt"
"log"
"math/big"
"os"
)
// Constants
const DefaultPwLenght int = 20
const VersionString string = "0.1.0"
const PwLowerCharsHuman string = "abcdefghjkmnpqrstuvwxyz"
const PwUpperCharsHuman string = "ABCDEFGHJKMNPQRSTUVWXYZ"
const PwLowerChars string = "abcdefghijklmnopqrstuvwxyz"
const PwUpperChars string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const PwSpecialCharsHuman string = "\"#/\\$%&+-*"
const PwSpecialChars string = "\"#/!\\$%&+-*.,?=()[]{}:;~^|"
const PwNumbersHuman string = "23456789"
const PwNumbers string = "1234567890"
type cliOpts struct {
minPassLen int
maxPassLen int
numOfPass int
useComplex bool
useLowerCase bool
useUpperCase bool
useNumber bool
useSpecial bool
humanReadable bool
excludeChars string
showHelp bool
showVersion bool
}
var config cliOpts
// Read flags
func init() {
// Bool flags
flag.BoolVar(&config.useLowerCase, "L", true, "Use lower case characters in passwords")
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.humanReadable, "H", false, "Generate human-readable passwords")
flag.BoolVar(&config.showVersion, "v", false, "Show version")
// Int flags
flag.IntVar(&config.minPassLen, "m", 10, "Minimum password length")
flag.IntVar(&config.maxPassLen, "x", DefaultPwLenght, "Maxiumum password length")
flag.IntVar(&config.numOfPass, "n", 1, "Number of passwords to generate")
// TODO: Exclude chars are missing, yet
flag.Parse()
if config.showVersion {
_, _ = os.Stderr.WriteString("Advanced Password Generator v" + VersionString + "\n")
os.Exit(0)
}
}
func main() {
pwLength := config.minPassLen
if pwLength < config.minPassLen {
pwLength = config.minPassLen
}
if pwLength > config.maxPassLen {
pwLength = config.maxPassLen
}
if config.useComplex {
config.useUpperCase = true
config.useLowerCase = true
config.useSpecial = true
config.useNumber = true
config.humanReadable = false
}
pwUpperChars := PwUpperChars
pwLowerChars := PwLowerChars
pwNumbers := PwNumbers
pwSpecialChars := PwSpecialChars
if config.humanReadable {
pwUpperChars = PwUpperCharsHuman
pwLowerChars = PwLowerCharsHuman
pwNumbers = PwNumbersHuman
pwSpecialChars = PwSpecialCharsHuman
}
var charRange string
if config.useLowerCase {
charRange = charRange + pwLowerChars
}
if config.useUpperCase {
charRange = charRange + pwUpperChars
}
if config.useNumber {
charRange = charRange + pwNumbers
}
if config.useSpecial {
charRange = charRange + pwSpecialChars
}
/*
for i := 1; i <= config.numOfPass; i++ {
fmt.Println(i)
}
*/
pwString := getRandChar(&charRange, pwLength)
fmt.Println(pwString)
}
func getRandChar(charRange *string, pwLength int) string {
availCharsLength := len(*charRange)
charSlice := []byte(*charRange)
returnString := []byte{}
for i := 0; i < pwLength; i++ {
randNum := getRandNum(availCharsLength)
returnString = append(returnString, charSlice[randNum])
}
return string(returnString)
}
func getRandNum(maxNum int) int {
maxNumBigInt := big.NewInt(int64(maxNum))
randNum64, err := rand.Int(rand.Reader, maxNumBigInt)
if err != nil {
log.Fatal("An error occured generating random number: %v", err)
}
randNum := int(randNum64.Int64())
return randNum
}