2022-03-02 06:24:55 -05:00
|
|
|
package pwgenerator
|
|
|
|
|
|
|
|
import (
|
2022-03-03 04:26:44 -05:00
|
|
|
"crypto/rand"
|
|
|
|
"math/big"
|
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
|
|
|
)
|
|
|
|
|
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
|
|
|
|
}
|
2022-03-03 04:26:44 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-03-03 04:26:44 -05:00
|
|
|
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 {
|
2022-03-03 04:26:44 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
randInt64 = cryptoInt.Int64()
|
|
|
|
|
|
|
|
randInt = int(randInt64)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|