add password generator
This commit is contained in:
195
vendor/github.com/sethvargo/go-diceware/diceware/generate.go
generated
vendored
Normal file
195
vendor/github.com/sethvargo/go-diceware/diceware/generate.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
package diceware
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// sides is the number of sides on a die.
|
||||
var sides = big.NewInt(6)
|
||||
|
||||
var _ DicewareGenerator = (*Generator)(nil)
|
||||
|
||||
// Generator is the stateful generator which can be used to customize the word
|
||||
// list and other generation options.
|
||||
type Generator struct {
|
||||
wordList WordList
|
||||
randReader io.Reader
|
||||
}
|
||||
|
||||
// GeneratorInput is used as input to the NewGenerator function.
|
||||
type GeneratorInput struct {
|
||||
// WordList is the word list to use. There are built-in word lists like
|
||||
// WordListEffBig (default), WordListEffSmall, and WordListOriginal. You can
|
||||
// also bring your own word list by implementing the WordList interface.
|
||||
WordList WordList
|
||||
|
||||
// RandReader is an optional reader to use in place of the default
|
||||
// (crypto/rand.Reader), which can be used to generate repeatable sets of
|
||||
// words
|
||||
RandReader io.Reader
|
||||
}
|
||||
|
||||
// NewGenerator creates a new Generator from the specified configuration. If no
|
||||
// input is given, all the default values are used. This function is safe for
|
||||
// concurrent use.
|
||||
func NewGenerator(i *GeneratorInput) (*Generator, error) {
|
||||
if i == nil {
|
||||
i = new(GeneratorInput)
|
||||
}
|
||||
|
||||
if i.WordList == nil {
|
||||
i.WordList = WordListEffLarge()
|
||||
}
|
||||
|
||||
gen := &Generator{
|
||||
wordList: i.WordList,
|
||||
randReader: i.RandReader,
|
||||
}
|
||||
|
||||
if gen.randReader == nil {
|
||||
gen.randReader = rand.Reader
|
||||
}
|
||||
|
||||
return gen, nil
|
||||
}
|
||||
|
||||
// Generate generates a collection of diceware words, specified by the numWords
|
||||
// parameter.
|
||||
//
|
||||
// The algorithm is fast, but it's not designed to be performant, favoring
|
||||
// entropy over speed.
|
||||
//
|
||||
// This function is safe for concurrent use, but there is a possibility of
|
||||
// concurrent invocations generating overlapping words. To generate multiple
|
||||
// non-overlapping words, use a single invocation of the function and split the
|
||||
// resulting string list.
|
||||
func (g *Generator) Generate(numWords int) ([]string, error) {
|
||||
if typ, ok := g.wordList.(WordListNumWordser); ok {
|
||||
if l := typ.NumWords(); numWords > l {
|
||||
return nil, fmt.Errorf("number of requested words (%d) cannot exceed the size of the wordlist (%d)",
|
||||
numWords, l)
|
||||
}
|
||||
}
|
||||
|
||||
list := make([]string, 0, numWords)
|
||||
seen := make(map[string]struct{}, numWords)
|
||||
|
||||
for i := 0; i < numWords; i++ {
|
||||
n, err := g.RollWord(g.wordList.Digits())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
word := g.wordList.WordAt(n)
|
||||
if _, ok := seen[word]; ok {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, word)
|
||||
seen[word] = struct{}{}
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// MustGenerate is the same as Generate, but panics on error.
|
||||
func (g *Generator) MustGenerate(numWords int) []string {
|
||||
list, err := g.Generate(numWords)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// Generate - see Generator.Generate for usage.
|
||||
func Generate(numWords int) ([]string, error) {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gen.Generate(numWords)
|
||||
}
|
||||
|
||||
// MustGenerate - see Generator.MustGenerate for usage.
|
||||
func MustGenerate(numWords int) []string {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gen.MustGenerate(numWords)
|
||||
}
|
||||
|
||||
// GenerateWithWordList generates a list of the given number of words from the
|
||||
// given word list.
|
||||
func GenerateWithWordList(numWords int, wordList WordList) ([]string, error) {
|
||||
gen, err := NewGenerator(&GeneratorInput{
|
||||
WordList: wordList,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gen.Generate(numWords)
|
||||
}
|
||||
|
||||
// WordAt retrieves the word at the given index from EFF's large wordlist.
|
||||
//
|
||||
// Deprecated: Use WordList.WordAt instead.
|
||||
func WordAt(i int) string {
|
||||
return WordListEffLarge().WordAt(i)
|
||||
}
|
||||
|
||||
// RollDie rolls a single 6-sided die and returns a value between [1,6].
|
||||
//
|
||||
// Internally this creates a new Generator with a nil configuration and calls
|
||||
// Generator.RollDie.
|
||||
func RollDie() (int, error) {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return gen.RollDie()
|
||||
}
|
||||
|
||||
// RollWord rolls and aggregates dice to represent one word in the list. The
|
||||
// result is the index of the word in the list.
|
||||
//
|
||||
// Internally this creates a new Generator with a nil configuration and calls
|
||||
// Generator.RollWord.
|
||||
func RollWord(d int) (int, error) {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return gen.RollWord(d)
|
||||
}
|
||||
|
||||
// RollDie rolls a single 6-sided die and returns a value between [1,6].
|
||||
func (g *Generator) RollDie() (int, error) {
|
||||
r, err := rand.Int(g.randReader, sides)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to generate a random number: %w", err)
|
||||
}
|
||||
return int(r.Int64()) + 1, nil
|
||||
}
|
||||
|
||||
// RollWord rolls and aggregates dice to represent one word in the list. The
|
||||
// result is the index of the word in the list.
|
||||
func (g *Generator) RollWord(d int) (int, error) {
|
||||
var final int
|
||||
|
||||
for i := d; i > 0; i-- {
|
||||
res, err := g.RollDie()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
final += res * int(math.Pow(10, float64(i-1)))
|
||||
}
|
||||
|
||||
return final, nil
|
||||
}
|
||||
Reference in New Issue
Block a user