generate.go

v1.0.0
Doc Versions Source
1
package bitwarden
2
3
import (
4
	"crypto/rand"
5
	"fmt"
6
	"math/big"
7
	"strings"
8
)
9
10
func generatePassword(opts GenerateOptions) (string, error) {
11
	if opts.Passphrase != nil && *opts.Passphrase {
12
		return generatePassphrase(opts)
13
	}
14
	return generateRandomPassword(opts)
15
}
16
17
func generateRandomPassword(opts GenerateOptions) (string, error) {
18
	length := 14
19
	if opts.Length != nil && *opts.Length > 0 {
20
		length = *opts.Length
21
	}
22
23
	var charset string
24
	if opts.Lowercase == nil || *opts.Lowercase {
25
		charset += "abcdefghijklmnopqrstuvwxyz"
26
	}
27
	if opts.Uppercase == nil || *opts.Uppercase {
28
		charset += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
29
	}
30
	if opts.Number != nil && *opts.Number {
31
		charset += "0123456789"
32
	}
33
	if opts.Special != nil && *opts.Special {
34
		charset += "!@#$%^&*()-_=+[]{}|;:',.<>?/"
35
	}
36
37
	if charset == "" {
38
		charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
39
	}
40
41
	result := make([]byte, length)
42
	for i := range result {
43
		idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
44
		if err != nil {
45
			return "", fmt.Errorf("generate random: %w", err)
46
		}
47
		result[i] = charset[idx.Int64()]
48
	}
49
	return string(result), nil
50
}
51
52
func generatePassphrase(opts GenerateOptions) (string, error) {
53
	numWords := 3
54
	if opts.Words != nil && *opts.Words > 0 {
55
		numWords = *opts.Words
56
	}
57
58
	separator := " "
59
	if opts.Separator != nil {
60
		separator = *opts.Separator
61
	}
62
63
	wordList := effLargeWordList[:]
64
	words := make([]string, numWords)
65
	for i := range words {
66
		idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(wordList))))
67
		if err != nil {
68
			return "", fmt.Errorf("generate random: %w", err)
69
		}
70
		w := wordList[idx.Int64()]
71
		if opts.Capitalize != nil && *opts.Capitalize && len(w) > 0 {
72
			w = strings.ToUpper(w[:1]) + w[1:]
73
		}
74
		words[i] = w
75
	}
76
77
	result := strings.Join(words, separator)
78
79
	if opts.IncludeNumber != nil && *opts.IncludeNumber {
80
		n, err := rand.Int(rand.Reader, big.NewInt(10))
81
		if err != nil {
82
			return "", fmt.Errorf("generate random: %w", err)
83
		}
84
		result += fmt.Sprintf("%d", n.Int64())
85
	}
86
87
	return result, nil
88
}
89

Source Files