add password generator

This commit is contained in:
2025-03-07 12:33:40 -05:00
parent 116be25489
commit 0d386e2d9f
27 changed files with 17895 additions and 42 deletions

20
vendor/github.com/sethvargo/go-diceware/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright 2017 Seth Vargo <seth@sethvargo.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View 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
}

View File

@@ -0,0 +1,6 @@
package diceware
type DicewareGenerator interface {
Generate(int) ([]string, error)
MustGenerate(int) []string
}

View File

@@ -0,0 +1,38 @@
package diceware
var _ DicewareGenerator = (*mockGenerator)(nil)
type mockGenerator struct {
result []string
err error
}
// NewMockGenerator creates a new generator that satisfies the DicewareGenerator
// interface. If an error is provided, the error is returned. If a result if
// provided, the result is always returned, regardless of what parameters are
// passed into the Generate or MustGenerate methods.
//
// This function is most useful for tests where you want to have predicable
// results for a transitive resource that depends on go-diceware.
func NewMockGenerator(result []string, err error) *mockGenerator {
return &mockGenerator{
result: result,
err: err,
}
}
// Generate returns the mocked result or error.
func (g *mockGenerator) Generate(int) ([]string, error) {
if g.err != nil {
return nil, g.err
}
return g.result, nil
}
// MustGenerate returns the mocked result or panics if an error was given.
func (g *mockGenerator) MustGenerate(int) []string {
if g.err != nil {
panic(g.err)
}
return g.result
}

View File

@@ -0,0 +1,42 @@
package diceware
// WordList is an interface that must be implemented to be considered a word
// list for use in the diceware algorithm. This interface can be implemented by
// other libraries.
type WordList interface {
// Digits is the number of digits for indexes in the word list. This
// determines the number of dice rolls.
Digits() int
// WordAt returns the word at the given integer in the word list.
WordAt(int) string
}
// WordListNumWordser is an auxiliary interface that returns the number of words
// in the list. This is a separate interface for backwards compatibility.
type WordListNumWordser interface {
// NumWords returns the total number of words in the list.
NumWords() int
}
var (
_ WordList = (*wordListInternal)(nil)
_ WordListNumWordser = (*wordListInternal)(nil)
)
type wordListInternal struct {
digits int
words map[int]string
}
func (w *wordListInternal) Digits() int {
return w.digits
}
func (w *wordListInternal) WordAt(i int) string {
return w.words[i]
}
func (w *wordListInternal) NumWords() int {
return len(w.words)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff