Initial commit
This commit is contained in:
commit
7fcc002e02
194
specialpass.go
Normal file
194
specialpass.go
Normal file
@ -0,0 +1,194 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"code.google.com/p/gopass"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"crypto/sha512"
|
||||
)
|
||||
|
||||
type PasswordRestrictions struct {
|
||||
name string
|
||||
minLength int
|
||||
maxLength int
|
||||
alphaLowerMin int
|
||||
alphaLowerMax int
|
||||
alphaUpperMin int
|
||||
alphaUpperMax int
|
||||
numberMin int
|
||||
numberMax int
|
||||
specialMin int
|
||||
specialMax int
|
||||
allowedSpecial string
|
||||
}
|
||||
|
||||
var siteName string
|
||||
|
||||
const DEFAULT_SITE = "etrade"
|
||||
|
||||
var sites []PasswordRestrictions = []PasswordRestrictions{
|
||||
PasswordRestrictions{
|
||||
name: "etrade",
|
||||
minLength: 6,
|
||||
maxLength: 32,
|
||||
alphaLowerMin: 0,
|
||||
alphaLowerMax: 32,
|
||||
alphaUpperMin: 0,
|
||||
alphaUpperMax: 32,
|
||||
numberMin: 1,
|
||||
numberMax: 32,
|
||||
specialMin: 0,
|
||||
specialMax: 0},
|
||||
PasswordRestrictions{
|
||||
name: "fidelity",
|
||||
minLength: 6,
|
||||
maxLength: 12,
|
||||
alphaLowerMin: 0,
|
||||
alphaLowerMax: 12,
|
||||
alphaUpperMin: 0,
|
||||
alphaUpperMax: 12,
|
||||
numberMin: 0,
|
||||
numberMax: 12,
|
||||
specialMin: 0,
|
||||
specialMax: 0},
|
||||
}
|
||||
|
||||
func init() {
|
||||
const site_usage = "Name of site for which to generate password"
|
||||
flag.StringVar(&siteName, "siteName", DEFAULT_SITE, site_usage)
|
||||
flag.StringVar(&siteName, "s", DEFAULT_SITE, site_usage+" (shorthand)")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var restrictions *PasswordRestrictions
|
||||
for _, v := range sites {
|
||||
if strings.ToLower(siteName) == strings.ToLower(v.name) {
|
||||
restrictions = &v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if restrictions == nil {
|
||||
fmt.Println("Error: Site name not recognized, please use one of the following:")
|
||||
for _, v := range sites {
|
||||
fmt.Println("\t" + v.name)
|
||||
}
|
||||
}
|
||||
|
||||
oldPassword, err := gopass.GetPass("Enter Password: ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c := make(chan int)
|
||||
go generateBytes(c, oldPassword, restrictions.name)
|
||||
|
||||
maxValue := 62 /*alphanumeric*/ + len(restrictions.allowedSpecial)
|
||||
|
||||
curAlphaLower := 0
|
||||
curAlphaUpper := 0
|
||||
curNumber := 0
|
||||
curSpecial := 0
|
||||
password := ""
|
||||
|
||||
lower := "abcdefghijklmnopqrstuvwxyz"
|
||||
upper := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
numbers := "0123456789"
|
||||
|
||||
//build up the initial string, making sure we don't go over the max allowed for each type
|
||||
for length := 0; length < restrictions.maxLength; length++ {
|
||||
val := <- c % maxValue
|
||||
switch {
|
||||
case val >= 0 && val < 26:
|
||||
if curAlphaLower + 1 <= restrictions.alphaLowerMax {
|
||||
password += lower[val:val+1]
|
||||
curAlphaLower++
|
||||
}
|
||||
case val >= 26 && val < 52:
|
||||
if curAlphaUpper + 1 <= restrictions.alphaUpperMax {
|
||||
password += upper[val-26:val-25]
|
||||
curAlphaUpper++
|
||||
}
|
||||
case val >= 52 && val < 62:
|
||||
if curNumber + 1 <= restrictions.numberMax {
|
||||
password += numbers[val-52:val-51]
|
||||
curNumber++
|
||||
}
|
||||
default:
|
||||
if curSpecial + 1 <= restrictions.specialMax {
|
||||
password += restrictions.allowedSpecial[val-62:val-61]
|
||||
curSpecial++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//now, make sure we meet the minimum requirements. If we don't, start replacing items in the password
|
||||
for {
|
||||
removed := true
|
||||
switch {
|
||||
case curAlphaLower < restrictions.alphaLowerMin:
|
||||
val := <- c % 26
|
||||
password += lower[val:val+1]
|
||||
curAlphaLower++
|
||||
case curAlphaUpper < restrictions.alphaUpperMin:
|
||||
val := <- c % 26
|
||||
password += upper[val:val+1]
|
||||
curAlphaUpper++
|
||||
case curNumber < restrictions.numberMin:
|
||||
val := <- c % 10
|
||||
password += numbers[val:val+1]
|
||||
curNumber++
|
||||
case curSpecial < restrictions.specialMin:
|
||||
val := <- c % len(restrictions.allowedSpecial)
|
||||
password += restrictions.allowedSpecial[val:val+1]
|
||||
curSpecial++
|
||||
default:
|
||||
removed = false
|
||||
}
|
||||
if !removed {
|
||||
break
|
||||
}
|
||||
|
||||
removedChar := password[:1]
|
||||
password = password[1:]
|
||||
|
||||
switch{
|
||||
case strings.Contains(lower, removedChar):
|
||||
curAlphaLower--
|
||||
case strings.Contains(upper, removedChar):
|
||||
curAlphaUpper--
|
||||
case strings.Contains(numbers, removedChar):
|
||||
curNumber--
|
||||
case strings.Contains(restrictions.allowedSpecial, removedChar):
|
||||
curSpecial--
|
||||
default:
|
||||
panic("Unknown character made its way into the password")
|
||||
}
|
||||
}
|
||||
|
||||
//finally, (pseudo-)randomize the password ordering, one element at a time
|
||||
for i := 0; i < restrictions.maxLength; i++ {
|
||||
position := (<- c % (restrictions.maxLength - i)) + i
|
||||
password = password[position:position+1] + password[0:position] + password[position+1:restrictions.maxLength]
|
||||
}
|
||||
|
||||
fmt.Println("Generated password for " + restrictions.name + ": " + password)
|
||||
}
|
||||
|
||||
func generateBytes(c chan int, password string, siteName string) {
|
||||
h := sha512.New()
|
||||
io.WriteString(h, password + strings.ToLower(siteName))
|
||||
hashBytes := h.Sum(nil)
|
||||
|
||||
for {
|
||||
for _, b := range hashBytes {
|
||||
c <- int(b)
|
||||
}
|
||||
h.Write(hashBytes)
|
||||
hashBytes = h.Sum(nil)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user