-
Notifications
You must be signed in to change notification settings - Fork 0
/
argon2_test.go
198 lines (157 loc) · 3.62 KB
/
argon2_test.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
package argon2_test
import (
"crypto/rand"
"math/big"
"os"
"testing"
"github.com/rackorbit/argon2"
)
func TestMain(m *testing.M) {
initDataset()
os.Exit(m.Run())
}
func TestHash(t *testing.T) {
if dataset == nil {
panic("test dataset is empty")
}
if numberOfPasswords != len(dataset) {
t.Fatalf("dataset failed to generate")
return
}
for i, password := range dataset {
password, err := argon2.Hash([]byte(password))
if err != nil {
t.Errorf("Test #%d: Should not have error return value, but received \"%v\"", i, err)
continue
}
if password == nil {
t.Errorf("Test #%d: Expected non-nil value, but got one", i)
continue
}
hashes = append(hashes, password)
}
if numberOfPasswords != len(hashes) {
t.Fatalf("hashset failed to generate")
return
}
}
var _hash []byte
func BenchmarkHash(b *testing.B) {
numberOfPasswords = b.N
initDataset()
if dataset == nil {
panic("test dataset is empty")
}
b.Run("Hash", func(b *testing.B) {
var h []byte
for i := 0; i < b.N; i++ {
h, _ = argon2.Hash([]byte(dataset[i]))
}
_hash = h
})
}
func TestVerify(t *testing.T) {
if dataset == nil {
panic("test dataset is empty")
}
t.Run("With Valid Password", func(t *testing.T) {
for i, password := range dataset {
if err := argon2.Verify([]byte(password), hashes[i]); err != nil {
t.Errorf("Test #%d: Should not have error return value, but received \"%v\"", i, err)
continue
}
}
})
t.Run("With Invalid Password", func(t *testing.T) {
for i, password := range dataset {
if err := argon2.Verify([]byte(password[:len(password)-1]), hashes[i]); err != argon2.ErrFailedVerify {
t.Errorf("Test #%d: Should've received ErrFailedVerify, but received \"%v\"", i, err)
continue
}
}
})
}
// ---------------------------------- \\
const (
lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"
uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
digits = "0123456789"
symbols = "~!@#$%^&*()-={}|[]\\:\"<>?,./"
)
var numberOfPasswords = 10
var (
dataset []string
hashes [][]byte
)
func initDataset() {
if dataset != nil {
return
}
for i := 0; i < numberOfPasswords; i++ {
p, err := generatePassword(96, 8, 12)
if err != nil {
panic(err)
return
}
dataset = append(dataset, p)
}
}
func generatePassword(length, numDigits, numSymbols int) (string, error) {
letters := lowercaseLetters + uppercaseLetters
chars := length - numDigits - numSymbols
var result string
// Characters
for i := 0; i < chars; i++ {
ch, err := randomElement(letters)
if err != nil {
return "", err
}
result, err = randomInsert(result, ch)
if err != nil {
return "", err
}
}
// Digits
for i := 0; i < numDigits; i++ {
d, err := randomElement(digits)
if err != nil {
return "", err
}
result, err = randomInsert(result, d)
if err != nil {
return "", err
}
}
// Symbols
for i := 0; i < numSymbols; i++ {
sym, err := randomElement(symbols)
if err != nil {
return "", err
}
result, err = randomInsert(result, sym)
if err != nil {
return "", err
}
}
return result, nil
}
// randomInsert randomly inserts the given value into the given string.
func randomInsert(s, val string) (string, error) {
if s == "" {
return val, nil
}
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(s)+1)))
if err != nil {
return "", err
}
i := n.Int64()
return s[0:i] + val + s[i:], nil
}
// randomElement extracts a random element from the given string.
func randomElement(s string) (string, error) {
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(s))))
if err != nil {
return "", err
}
return string(s[n.Int64()]), nil
}