PWGen/pwgenerator/funcs.go

114 lines
2.1 KiB
Go
Raw Normal View History

2022-03-02 06:24:55 -05:00
package pwgenerator
import (
"crypto/rand"
"math/big"
insecureRand "math/rand"
2022-03-02 06:24:55 -05:00
"sort"
2022-03-03 05:51:22 -05:00
"strings"
2022-03-02 06:24:55 -05:00
)
// newCryptoShuffler returns a new cryptoShuffler.
func newCryptoShuffler() *cryptoShuffler {
return new(cryptoShuffler)
}
2022-03-03 05:51:22 -05:00
/*
GetCharset returns a CharSet from a set of characters.
chars can be one of []rune, []byte, []string, or string.
*/
func GetCharset(chars interface{}) (charset CharSet, err error) {
switch t := chars.(type) {
case []rune:
charset = CharSet(string(t))
case []byte:
charset = CharSet(string(t))
case []string:
s := strings.Join(t, "")
charset = CharSet(s)
case string:
charset = CharSet(t)
default:
err = ErrBadType
return
}
return
}
2022-03-02 06:24:55 -05:00
// sortDedupe sorts a slice of runes and deduplicates them.
func sortDedupe(charset *CharSet) {
var vals map[Char]bool = make(map[Char]bool)
var sorted CharSet
var idx int
// This inherently dedupes.
for _, i := range *charset {
vals[i] = true
}
// This handles sorting.
sorted = make(CharSet, len(vals))
// First we need a slice (again).
for k := range vals {
sorted[idx] = k
idx++
}
// And now we can sort...
sort.Sort(&sorted)
// And replace the original charset with the sorted, deduplicated one.
*charset = sorted
return
}
/*
saferRandInt uses crypto/rand instead of math/rand to get a random number.
While this is cryptographically safer, I guarantee it's a much bigger pain to do.
*/
func saferRandInt(max int) (randInt int, err error) {
2022-03-03 05:51:22 -05:00
// Avoid a panic on max being 0 per rand.Int.
if max == 0 {
max = 1
}
var max64 int64 = int64(max)
var cryptoInt *big.Int = big.NewInt(max64)
var randInt64 int64
2022-03-03 05:51:22 -05:00
if cryptoInt, err = rand.Int(rand.Reader, cryptoInt); err != nil {
return
}
randInt64 = cryptoInt.Int64()
randInt = int(randInt64)
return
}
// passwordShuffle shuffles a password's characters ordering so we don't have the condition satisfiers in the beginning.
func passwordShuffle(passwd *string) {
var r *insecureRand.Rand = insecureRand.New(newCryptoShuffler())
r.Shuffle(
len(*passwd),
func(i, j int) {
var chars []rune = []rune(*passwd)
chars[i], chars[j] = chars[j], chars[i]
*passwd = string(chars)
},
)
return
}