-
Notifications
You must be signed in to change notification settings - Fork 0
/
scrypt.go
92 lines (77 loc) · 1.75 KB
/
scrypt.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
91
92
package password
import (
"encoding/base64"
"strconv"
"strings"
"golang.org/x/crypto/scrypt"
)
const (
blockSize = 1 << 3
maxMemory = 0
parallelism = 1
workFactor = 1 << 14
keyLen = 64
)
type scryptHasher struct {
salt string
}
func (hasher *scryptHasher) Encode(password string) (string, error) {
return hasher.encode(password, hasher.salt)
}
func (hasher *scryptHasher) encode(password, salt string) (string, error) {
dk, err := scrypt.Key(
[]byte(password),
[]byte(salt),
workFactor,
blockSize,
parallelism,
keyLen)
if err != nil {
return "", err
}
hash := base64.StdEncoding.EncodeToString(dk)
parts := []string{
scryptAlgo,
strconv.Itoa(workFactor),
hasher.salt,
strconv.Itoa(blockSize),
strconv.Itoa(parallelism),
hash,
}
return strings.Join(parts, sep), nil
}
func (hasher *scryptHasher) Decode(encoded string) (*PasswordInfo, error) {
parts := strings.SplitN(encoded, sep, 6)
if parts[0] != scryptAlgo {
return nil, errUnknownAlgorithm
}
return &PasswordInfo{
Algorithm: scryptAlgo,
Hash: parts[5],
Salt: parts[2],
}, nil
}
func (hasher *scryptHasher) Verify(password, encoded string) bool {
pi, err := hasher.Decode(encoded)
if err != nil {
return false
}
encoded2, err := hasher.encode(password, pi.Salt)
if err != nil {
return false
}
return encoded2 == encoded
}
func (hasher *scryptHasher) MustUpdate(encoded string) bool {
pi, err := hasher.Decode(encoded)
if err != nil {
return false
}
return mustUpdateSalt(pi.Salt, saltEntropy) || len(pi.Salt) < len(hasher.salt)
}
func (hasher *scryptHasher) Harden(password, encoded string) (string, error) {
return encoded, nil
}
func newScryptHasher(opt *HasherOption) (Hasher, error) {
return &scryptHasher{salt: opt.Salt}, nil
}