mirror of
https://github.com/wneessen/apg-go.git
synced 2024-11-22 13:50:49 +01:00
v0.1.0: Initial check-in
This commit is contained in:
parent
ebdad33364
commit
5d743f70ae
8 changed files with 209 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,6 +4,7 @@
|
|||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
apg
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal 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
9
.idea/apg.go.iml
Normal 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>
|
12
.idea/inspectionProfiles/Project_Default.xml
Normal file
12
.idea/inspectionProfiles/Project_Default.xml
Normal 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
8
.idea/modules.xml
Normal 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
6
.idea/vcs.xml
Normal 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>
|
30
README.md
30
README.md
|
@ -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
136
apg.go
Normal 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
|
||||
}
|
Loading…
Reference in a new issue