Documentation
¶
Overview ¶
Package spg provides 1Password's Strong Password Generator engine for uniform and flexible password generation.
The Strong Password Generator package offers the underlying engine for flexible specification of generated password requirements and ensuring that the generated passwords it returns follow a uniform distribution.
The clients of this package are expected to manage what is presented to users. This engine offers far greater flexibility than should normally be exposed to users.
Usage overview ¶
The very highlevel usage over view for most cases is ¶
1. The user will create either a character recipe, r, with NewCharRecipe() or a word (or syllable) list recipe, r, with NewWLRecipe().
2. The user will call the r.Generate() method of a recipe, r, to generate a password, pwd.
3. The returned password, pwd, has a String() method, which does the obvious thing and Entropy field, which contains the min-Entropy based on the recipe.
Wordlist and pronounceable ¶
The word list generator produces things like "correct horse battery staple", but when the list is of pronounceable syllables, it can also be set up to produce things like
Mirk9vust8jilk3rooy scuy9lam2lerk9Kais smoh1fock6mirn7Lic jaud3Rew4jo6mont
Lengths for these are specified in terms of the number of elements drawn from the list to be included in these passwords (not counting the separators). Although the above examples all have different lengths in terms of number of characters, they were all specified as Length 4.
The passwords that one gets depend on the word list recipe, WLRecipe, and the actual word list provided.
Character passwords ¶
Character-based are your typical notion of generated password, however these can be specified in ways to produce only numeric PINs if desired. The passwords generated are a function of the CharRecipe.
The Generate and Entropy methods ¶
The word list and character recipes (WLRecipe, CharRecipe) implement a Generator interface with two methods, Generate and Entropy.
Generate returns a Password. There is a fair amount of internal structure to a Password object, but the ones you are most after is available through the Password.String() method and the Entropy field.
Entropy returns the entropy of a password that would be generated given the current recipe.
A word about Entropy ¶
Entropy is a highly misleading concept when applied to passwords. In the general case it is either an incoherent concept or the wrong concept to use when talking about the strength of a password. It does, however, make sense when a password is drawn uniformly from a space of possible passwords. When the distribution is uniform, the (Shannon) entropy is the same as the min-entropy (based on probability of getting the most likely result).
This package does ensure that passwords are generated uniformly given the recipe passed to the generator, with the exception of the interaction of capitalizaton for some wordlists. In those cases, min-entropy is reported. That is, where min-entropy is not the same as Shannon Entropy Entropy() returns the min-entropy.
Entropy is a function solely of the recipe.
License ¶
This package is Copyright 2017, 2018 by AgileBits, Inc and is licensed under the Apache 2.0 agreement.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( MaxTrials = 200 // How many times we will try to generate before giving up MaxFailRate = 1.0 / 1000000000 // Maximum acceptable failure rate after MaxTrials )
Re-generation trials for meeting requirements
var ( SFNone SFFunction = func() (string, FloatE) { return "", FloatE(0.0) } // Empty separator SFDigits1 = NewSFFunction(CharRecipe{Length: 1, Allow: Digits}) // Single digit separator SFDigits2 = NewSFFunction(CharRecipe{Length: 2, Allow: Digits}) // Double digit separator SFDigitsNoAmbiguous1 = NewSFFunction(CharRecipe{Length: 1, Allow: Digits, Exclude: Ambiguous}) // Single digit, no ambiguous SFDigitsNoAmbiguous2 = NewSFFunction(CharRecipe{Length: 2, Allow: Digits, Exclude: Ambiguous}) // Double digit, no ambiguous SFSymbols = NewSFFunction(CharRecipe{Length: 1, Allow: Symbols}) // Symbols SFDigitsSymbols = NewSFFunction(CharRecipe{Length: 1, Allow: Symbols | Digits}) // Symbols and digits )
Pre-baked Separator functions
var AgileSyllables = []string{}/* 10129 elements not displayed */
AgileSyllables is the list of syllables used by the 1Password strong password generator
var AgileWords = []string{}/* 18325 elements not displayed */
AgileWords is the list of words used by the 1Password strong password generator
Functions ¶
This section is empty.
Types ¶
type CapScheme ¶
type CapScheme string
CapScheme is for an enumeration of capitalization schemes
const ( CSNone CapScheme = "none" // No words will be capitalized CSFirst CapScheme = "first" // First word will be capitalized CSAll CapScheme = "all" // All words will be capitalized CSRandom CapScheme = "random" // Some words (roughly half) will be capitalized CSOne CapScheme = "one" // One randomly selected word will be capitalized )
Defined capitalization schemes. (Using strings instead of int enum to make life easier in a debugger and calling from JavaScript)
type CharRecipe ¶
type CharRecipe struct { Length int // Length of generated password in characters // Character types to Allow, Require, or Exclude in generated password Allow CTFlag // Types which may appear Require CTFlag // Types which must appear (at least one from each type) Exclude CTFlag // Types must not appear // User provided character sets for Allow, Require, and Exclude AllowChars string // Specific characters that may appear RequireSets []string // At least one character from each string must appear ExcludeChars string // Specific characters that must not appear // contains filtered or unexported fields }
CharRecipe are generator attributes relevent for character list generation
Allow - Any character from any of these sets may be present in generated password.
Exclude - No characters from any of these sets may be present in the generated password. Exclusion overrides Require and Allow.
Require - At least one character from each of these sets must be present in the generated password.
Example (Default) ¶
r := NewCharRecipe(15) // 15 character passwords // Let's generate 5 passwords to get a small taste of them for i := 0; i < 5; i++ { p, _ := r.Generate() // You'd check for errors in real code fmt.Printf("Password: %q\tEntropy: %.3f\n", p, p.Entropy) }
Output:
Example (Lowerdigits) ¶
r := CharRecipe{ Length: 17, // Password will be 17 characters long Allow: Lowers | Digits, // and may contain lowercase letters and digits Exclude: Ambiguous, // but no ambiguous characters } // Let's generate five of them for a small sample for i := 0; i < 5; i++ { p, _ := r.Generate() // You would check error in real code fmt.Printf("Password: %q\tEntropy: %.3f\n", p, p.Entropy) }
Output:
Example (Pin) ¶
Examples Because these have random output, we can't use "Output:",
r := CharRecipe{ Length: 4, // Password will be 4 characters long Allow: Digits, // and comprised of digits } pwd, _ := r.Generate() // In real code, you would check error fmt.Println(pwd)
Output:
func NewCharRecipe ¶
func NewCharRecipe(length int) *CharRecipe
NewCharRecipe creates CharRecipe with reasonable defaults and Length length Defaults are
r.Allow = Letters | Digits | Symbols r.Exclude = Ambiguous
And these may need to be cleared if you want to tinker with them
func (CharRecipe) Alphabet ¶
func (r CharRecipe) Alphabet() string
Alphabet returns a sorted string of the characters that are drawn from in a given recipe, r
func (CharRecipe) Entropy ¶
func (r CharRecipe) Entropy() float32
Entropy returns the entropy of a character password given the generator attributes
func (CharRecipe) Generate ¶
func (r CharRecipe) Generate() (*Password, error)
Generate a password using the character generator. The attributes contain all of the details needed for generating the password
func (CharRecipe) SuccessProbability ¶
func (r CharRecipe) SuccessProbability() float32
SuccessProbability returns the chances of meeting all of the Require-ments on a single trial.
type FloatE ¶
type FloatE float32
FloatE is the float type bits of a generated password. It is only useful (externally) if you are creating your own Password SeparatorFunc.
type IndexKind ¶
type IndexKind uint8
IndexKind is the kind of tokenization index. Token indices are compact byte arrays that can be used in conjunction to with a password string to reconstruct an array of Tokens
const ( CharacterIndexKind IndexKind = iota // Tokens are all Atoms and of length 1 VarAtomsIndexKind // Tokes are all atoms (of potentally varying lengths) AlternatingIndexKind // Tokens are alternation of A S A S ... A FullIndexKind // Requires a full token index as sequeunce of token types is not predictable )
Possible values for first byte of the compact token index index.
type Indices ¶
type Indices []byte
Indices can hold the indices needed to reconstruct tokens, separator from string
type Password ¶
type Password struct { Entropy float32 // Entropy in bits of the Recipe from which this password was generated // contains filtered or unexported fields }
Password is what gets generated by the Generators
func Tokenize ¶
Tokenize reconstructs a Password from a password string and Indices produced by MakeIndices()
type SFFunction ¶
SFFunction is a type for a function that returns a string (to be used within a password) and the entropy it contributes
func NewSFFunction ¶
func NewSFFunction(r CharRecipe) SFFunction
NewSFFunction makes a Separator Function from a CharRecipe
type Token ¶
type Token struct {
// contains filtered or unexported fields
}
Token is a unit within a generated password. In "correct horse battery" there are five tokens
[]Token{ {Value: "correct", Type: AtomType}, {Value: " ", Type: SeparatorType}, {Value: "horse", Type: AtomType}, {Value: " ", Type: SeparatorType}, {Value: "battery", Type: AtomType}, }
type TokenType ¶
type TokenType uint8
TokenType holds the kinds of tokens within within a generated password Having it be an uint8 makes it easier to compact these into the token indices
type Tokens ¶
type Tokens []Token
Tokens is the array of tokens that comprise a password. Its purpose is to allow some consumer of generated passwords to be able to display a wordlist password with knowledge of where the units and separators are. For example, the separators within a wordlist password might be displayed in a different color.
Tokens is also intended to be a relatively compact entity.
func (Tokens) Atoms ¶
Atoms returns the tokens (words, syllables, characters) that compromise the bulk of the password
func (Tokens) Kind ¶
Kind looks at the tokens and works out what the most appropriate kind of token index we should use. It is exported in case callers would like help at guessing what kind of password they have, it does only provide a guess. It is no substitute for the original recipe
func (Tokens) MakeIndices ¶
MakeIndices returns a compact array of indices that indicate where a string is to be separated In the worst case it will need to encode both the length and the type of each token, thus requiring two bytes per token (plus the one leading byte) It does attempt to inspect the tokens to determine whether it can get away with encoding less information. The leading byte of the returned array contains necessary information about the particularly indexing used
token lengths must be in (1, 255)
func (Tokens) Separators ¶
Separators are the separators between tokens. If this list is shorter than one less then the number of tokens, the last separator listed is used repeatedly to separate subsequent tokens. If this is nil, it is taken as nil no separators between tokens
type WLRecipe ¶
type WLRecipe struct { Length int // Length of generated password in words SeparatorChar string // What character(s) should separate words SeparatorFunc SFFunction // function to generate separators, If nil just use SeperatorChar Capitalize CapScheme // Which words in generated password should be capitalized // contains filtered or unexported fields }
WLRecipe (Word List password Attributes) are the generator settings for wordlist (syllable list) passwords
Example (Once) ¶
// You would use a much longer wordlist, probably taken from a file w := []string{"once", "upon", "midnight", "dreary", "while", "pondered", "weak", "and", "weary", "over", "many"} wl, err := NewWordList(w) // Prepares list for use in recipe creation if err != nil { log.Fatalf("Oops: %v", err) } // Four word passwords with digit separator and one of the words capitalized r := NewWLRecipe(4, wl) r.SeparatorFunc = SFDigits1 r.Capitalize = CSOne pwd, err := r.Generate() if err != nil { log.Fatalf("Oops: %v", err) } // With random output, we can't list expected Output // So uncomment the following, but test will fail _ = pwd // Make go happy for when pwd isn't used // fmt.Printf("Password: \t%q\n", pwd) e := r.Entropy() fmt.Printf("Entropy: \t%.2f\n", e)
Output: Entropy: 25.80
func NewWLRecipe ¶
NewWLRecipe sets up word list password attributes with defaults and Length length
func (WLRecipe) Entropy ¶
Entropy returns the min-entropy from the recipe. It needs to know things about the wordlist used as well as other details of the recipe.
When the generator produces uniform distirbution (the typical case) min-entropy and Shannon entropy are the same. If capitalization is used and the word list contains members whose capitalization does not yield a distinct element, the distribution becomes non-uniform.
type WordList ¶
type WordList struct {
// contains filtered or unexported fields
}
WordList contains the list of words WLGenerator()
func NewWordList ¶
NewWordList does what it says on the tin. Pass it a slice of strings It will remove duplicates from the slice provided, and it will count up how many words on the list can be changed through capitalization This isn't cheap, so it is best to create each word list once and keep it around as long as you need it.