-
-
Notifications
You must be signed in to change notification settings - Fork 479
/
pwgen.go
90 lines (74 loc) · 2.55 KB
/
pwgen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Package pwgen implements multiple popular password generate algorithms.
// It supports creating classic cryptic passwords with different character
// classes as well as more recent memorable approaches.
//
// Some methods try to ensure certain requirements are met and can be very slow.
package pwgen
import (
"fmt"
"os"
"strings"
)
// ErrMaxTries is returned when the maximum number of tries is reached.
var ErrMaxTries = fmt.Errorf("maximum tries exceeded")
// Character classes.
const (
Digits = "0123456789"
Upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Lower = "abcdefghijklmnopqrstuvwxyz"
Syms = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
Ambiq = "0ODQ1IlB8G6S5Z2"
// CharAlpha is the class of letters.
CharAlpha = Upper + Lower
// CharAlphaNum is the class of alpha-numeric characters.
CharAlphaNum = Digits + Upper + Lower
// CharAll is the class of all characters.
CharAll = Digits + Upper + Lower + Syms
)
// GeneratePassword generates a random, hard to remember password.
func GeneratePassword(length int, symbols bool) string {
chars := Digits + Upper + Lower
if symbols {
chars += Syms
}
if c := os.Getenv("GOPASS_CHARACTER_SET"); c != "" {
chars = c
}
return GeneratePasswordCharset(length, chars)
}
// GeneratePasswordCharset generates a random password from a given
// set of characters.
func GeneratePasswordCharset(length int, chars string) string {
c := NewCryptic(length, false)
c.Chars = chars
return c.Password()
}
// GeneratePasswordWithAllClasses tries to enforce a password which
// contains all character classes instead of only enabling them.
// This is especially useful for broken (corporate) password policies
// that mandate the use of certain character classes for no good reason.
func GeneratePasswordWithAllClasses(length int, symbols bool) (string, error) {
c := NewCrypticWithAllClasses(length, symbols)
if pw := c.Password(); pw != "" {
return pw, nil
}
return "", fmt.Errorf("failed to generate matching password after %d rounds: %w", c.MaxTries, ErrMaxTries)
}
// GeneratePasswordCharsetCheck generates a random password from a given
// set of characters and validates the generated password with crunchy.
func GeneratePasswordCharsetCheck(length int, chars string) string {
c := NewCrypticWithCrunchy(length, false)
c.Chars = chars
return c.Password()
}
// Prune removes all characters in cutset from the input.
func Prune(in string, cutset string) string {
out := make([]rune, 0, len(in))
for _, r := range in {
if strings.Contains(cutset, string(r)) {
continue
}
out = append(out, r)
}
return string(out)
}