2017-10-31 11:01:53 +00:00
|
|
|
package securepassword
|
|
|
|
|
|
|
|
import (
|
2024-04-06 22:52:39 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2017-10-31 11:01:53 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2024-04-06 22:52:39 +00:00
|
|
|
"golang.org/x/text/cases"
|
|
|
|
"golang.org/x/text/language"
|
2022-06-27 17:45:12 +00:00
|
|
|
|
2019-02-28 18:51:33 +00:00
|
|
|
"github.com/Luzifer/go_helpers/v2/str"
|
2017-10-31 11:01:53 +00:00
|
|
|
)
|
|
|
|
|
2024-04-06 22:52:39 +00:00
|
|
|
type (
|
|
|
|
// XKCD represents a XKCD-style password generator
|
|
|
|
XKCD struct {
|
|
|
|
// Separator to be used between words
|
|
|
|
Separator string
|
|
|
|
}
|
|
|
|
)
|
2017-10-31 11:01:53 +00:00
|
|
|
|
|
|
|
var (
|
|
|
|
// ErrTooFewWords represents an error thrown if the password will
|
|
|
|
// have fewer than four words and are not considered to be safe
|
|
|
|
ErrTooFewWords = errors.New("XKCD passwords with less than 4 words makes no sense")
|
|
|
|
// DefaultXKCD contains an default instance of the XKCD password
|
|
|
|
// generator
|
|
|
|
DefaultXKCD = NewXKCDGenerator()
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewXKCDGenerator initializes a new XKCD password generator
|
|
|
|
// https://xkcd.com/936/
|
|
|
|
func NewXKCDGenerator() *XKCD { return &XKCD{} }
|
|
|
|
|
|
|
|
// GeneratePassword generates a password with the number of words
|
|
|
|
// given and optionally the current date prepended
|
2024-04-06 22:52:39 +00:00
|
|
|
//
|
|
|
|
//revive:disable-next-line:flag-parameter
|
2017-10-31 11:01:53 +00:00
|
|
|
func (x XKCD) GeneratePassword(length int, addDate bool) (string, error) {
|
2022-06-27 17:41:47 +00:00
|
|
|
if length < minPasswordLength {
|
2017-10-31 11:01:53 +00:00
|
|
|
return "", ErrTooFewWords
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
password string
|
|
|
|
usedWords []string
|
|
|
|
)
|
|
|
|
|
|
|
|
if addDate {
|
|
|
|
password = time.Now().Format("20060102.")
|
|
|
|
}
|
|
|
|
|
|
|
|
for len(usedWords) < length {
|
2022-06-27 17:41:47 +00:00
|
|
|
widx, err := randIntn(len(xkcdWordList))
|
|
|
|
if err != nil {
|
2024-04-06 22:52:39 +00:00
|
|
|
return "", fmt.Errorf("generating random number: %w", err)
|
2022-06-27 17:41:47 +00:00
|
|
|
}
|
|
|
|
|
2024-04-06 22:52:39 +00:00
|
|
|
word := cases.Title(language.AmericanEnglish).String(xkcdWordList[widx])
|
2017-10-31 11:01:53 +00:00
|
|
|
if str.StringInSlice(word, usedWords) {
|
|
|
|
// Don't use a word twice
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
usedWords = append(usedWords, word)
|
|
|
|
}
|
|
|
|
|
2019-12-01 12:10:20 +00:00
|
|
|
return password + strings.Join(usedWords, x.Separator), nil
|
2017-10-31 11:01:53 +00:00
|
|
|
}
|