-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhotp_test.go
184 lines (152 loc) · 4.02 KB
/
hotp_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
package otp
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/base32"
"hash"
"reflect"
"testing"
)
const defaultSecret string = "12345678901234567890"
func TestHmacSha(t *testing.T) {
t.Parallel()
input := []byte("test-input")
bs := hmacSha(defaultSecret, input, sha1.New)
expected := []byte{206, 196, 29, 189, 198, 222, 88, 115, 62, 215, 116, 67, 206, 130, 89, 12, 146, 242, 197, 164}
if !reflect.DeepEqual(bs, expected) {
t.Errorf("HMAC SHA1 is wrong: %+v", bs)
}
}
func TestGenerate(t *testing.T) {
t.Parallel()
testValues := []string{"755224", "287082", "359152", "969429", "338314", "254676", "287922", "162583", "399871", "520489"}
for i, v := range testValues {
c := HotpConfig{Secret: defaultSecret, Count: i}
h := NewHOTP(&c)
h.Count = i
otp := h.Generate()
if otp != v {
t.Errorf("Expected %v to be %v", otp, v)
}
// Base32 tests
c.UseBase32 = true
c.Secret = base32.StdEncoding.EncodeToString([]byte(defaultSecret))
h32 := NewHOTP(&c)
h32.Count = i
otp32 := h32.Generate()
if otp32 != v {
t.Errorf("Expected base32 encoded %v to be %v", otp32, v)
}
}
}
func TestCheck_accurateCount(t *testing.T) {
t.Parallel()
c := HotpConfig{Secret: defaultSecret, Window: 1}
h := NewHOTP(&c)
v, i := h.Check("755224")
if !v || i != 0 {
t.Error("HOTP at spot 1 did not succeed")
}
}
func TestCheck_futureCount(t *testing.T) {
t.Parallel()
c := HotpConfig{Secret: defaultSecret, Count: 1, Window: 3}
h := NewHOTP(&c)
v, i := h.Check("969429")
if !v || i != 3 {
t.Error("HOTP did not count into the future as expected")
}
}
func TestCheck_failure(t *testing.T) {
t.Parallel()
c := HotpConfig{Secret: defaultSecret, Count: 2, Window: 3}
h := NewHOTP(&c)
v, _ := h.Check("520489")
if v {
t.Error("HOTP Check succeeded when expected to fail")
}
}
func TestSync(t *testing.T) {
t.Parallel()
c := HotpConfig{Secret: defaultSecret}
h := NewHOTP(&c)
v, i := h.Sync("755224", "287082")
if !v || i != 2 {
t.Error("HOTP Sync at beginning failed")
}
v, i = h.Sync("254676", "287922")
if !v || i != 7 {
t.Error("HOTP future sync failed")
}
v, _ = h.Sync("123456", "520489")
if v {
t.Error("HOTP expected to not find first OTP")
}
v, _ = h.Sync("254676", "520489")
if v {
t.Error("HOTP expected to not find second OTP")
}
}
func TestNewHotp_defaultConfig(t *testing.T) {
t.Parallel()
dConfig := HotpConfig{}
dToken := NewHOTP(&dConfig)
if len(dToken.Secret) != 20 ||
dToken.Count != 0 ||
dToken.Length != 6 ||
dToken.Window != 5 ||
dToken.IsBase32 {
t.Errorf("NewHOTP (default) returned an object with unexpected properties %+v", dToken)
}
}
func TestNewHotp_customConfig(t *testing.T) {
t.Parallel()
cConfig := HotpConfig{"secret", 5, 3, 100, true, "sha1"}
cToken := NewHOTP(&cConfig)
if cToken.Secret != "secret" ||
cToken.Count != 5 ||
cToken.Length != 3 ||
cToken.Window != 100 ||
!cToken.IsBase32 {
t.Errorf("NewHOTP (custom) returned an object with unexpected properties %+v", cToken)
}
}
func TestNewHotp_sha256(t *testing.T) {
t.Parallel()
hmac256Config := HotpConfig{
Crypto: "sha256",
}
hmac256Token := NewHOTP(&hmac256Config)
if hmac256Token.Hasher == nil {
t.Error("NewHOTP (hmac256) did not return a function")
}
hashers256Match := compareHashers(hmac256Token.Hasher, sha256.New)
if !hashers256Match {
t.Error("NewHOTP (hmac256) did not match the expected value")
}
}
func TestNewHotp_sha512(t *testing.T) {
t.Parallel()
hmac512Config := HotpConfig{
Crypto: "sha512",
}
hmac512Token := NewHOTP(&hmac512Config)
if hmac512Token.Hasher == nil {
t.Error("NewHOTP (hmac512) did not return a function")
}
hashers512Match := compareHashers(hmac512Token.Hasher, sha512.New)
if !hashers512Match {
t.Error("NewHOTP (hmac512) did not match the expected value")
}
}
func compareHashers(h1, h2 func() hash.Hash) bool {
key := []byte("hasher test key")
m := []byte("hasher test message")
s1 := hmac.New(h1, key)
s1.Write(m)
s2 := hmac.New(h2, key)
s2.Write(m)
return hmac.Equal(s1.Sum(nil), s2.Sum(nil))
}