-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpwd.go
More file actions
88 lines (75 loc) · 2.2 KB
/
pwd.go
File metadata and controls
88 lines (75 loc) · 2.2 KB
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
// Copyright Frontware International
// This package is used by several Frontware project to handle basic tasks about passwords
package pwd
import (
"bytes"
"crypto/rand"
_ "embed"
"hash/fnv"
"io"
"github.com/steakknife/bloomfilter"
"golang.org/x/crypto/bcrypt"
)
var (
bf *bloomfilter.Filter
//go:embed pwd.bf.gz
pwdBin []byte
)
func init() {
// Initialize bloom filter with list of passwords we get from embed pwd.bf.bz
r := bytes.NewReader(pwdBin)
bf, _, _ = bloomfilter.ReadFrom(r) // read the BF
}
// IsCommon returns true if the password is in the list of most common passwords.
// We use bloomfilter with a list of 1 million common passwords.
// IsCommon("qwerty") // returns true
// IsCommon("password") // returns true
// IsCommon("jkljfd5675fhgf6567H=") // returns false
func IsCommon(pwd string) bool {
h := fnv.New64()
h.Write([]byte(pwd))
return bf.Contains(h)
}
// HashPassword create a bcrypt hash
func HashPassword(pwd string) (string, error) {
password := []byte(pwd)
// Hashing the password with the default cost of 10
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedPassword), nil
}
// stdChars characters to be used in auto generated password
// We removed 1 and I to avoid confusion, sometimes they are very similar on the phone
var stdChars = []byte("ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz23456789")
// NewPassword returns a new password. Minimum length is 5
// NewPassword(4) // returns a random password of 5 chars
// NewPassword(8) // returns a random password of 8 chars
func NewPassword(length int) string {
if length < 5 {
length = 5
}
return randChar(length, stdChars)
}
// randChar returns random char, usually to generate password
func randChar(length int, chars []byte) string {
newPword := make([]byte, length)
randomData := make([]byte, length+(length/4)) // storage for random bytes.
clen := byte(len(chars))
maxrb := byte(256 - (256 % len(chars)))
i := 0
for {
io.ReadFull(rand.Reader, randomData)
for _, c := range randomData {
if c >= maxrb {
continue
}
newPword[i] = chars[c%clen]
i++
if i == length {
return string(newPword)
}
}
}
}