Skip to content
File

Blob: util/hashcash/hashcash_test.go

go332 lines
1package hashcash
2 
3import (
4 "crypto/rand"
5 "encoding/base64"
6 "errors"
7 "testing"
8 "time"
9)
10 
11var never = time.Date(3006, time.January, 1, 15, 4, 5, 0, time.UTC)
12 
13func TestNew(t *testing.T) {
14 h1 := New(Hashcash{})
15 
16 h2, err := Parse(h1.String())
17 if nil != err {
18 t.Fatal(err)
19 return
20 }
21 
22 if h1.Tag != h2.Tag {
23 t.Fatal("wrong tag version")
24 return
25 }
26 
27 if h1.Difficulty != h2.Difficulty {
28 t.Fatal("wrong difficulty")
29 return
30 }
31 
32 if h1.ExpiresAt != h2.ExpiresAt {
33 t.Fatal("wrong expiresat")
34 return
35 }
36 
37 if h1.Subject != h2.Subject {
38 t.Fatal("wrong subject")
39 return
40 }
41 
42 if h1.Nonce != h2.Nonce {
43 t.Fatal("wrong nonce")
44 return
45 }
46 
47 if h1.Alg != h2.Alg {
48 t.Fatal("wrong algorithm")
49 return
50 }
51 
52 if h1.Solution != h2.Solution {
53 t.Fatal("wrong solution")
54 return
55 }
56}
57 
58func TestExplicit(t *testing.T) {
59 nonce := make([]byte, 16)
60 _, _ = rand.Read(nonce)
61 h0 := Hashcash{
62 Tag: "H",
63 Difficulty: 1000,
64 ExpiresAt: time.Now().UTC().Truncate(time.Second),
65 Subject: "example.com",
66 Nonce: base64.RawURLEncoding.EncodeToString(nonce),
67 Alg: "FOOBAR",
68 Solution: "incorrect",
69 }
70 h1 := New(h0)
71 
72 h2, err := Parse(h1.String())
73 if nil != err {
74 t.Fatal(err)
75 return
76 }
77 h3 := New(*h2)
78 
79 if h0.Tag != h3.Tag {
80 t.Fatal("wrong tag version")
81 return
82 }
83 
84 if h0.Difficulty != h3.Difficulty {
85 t.Fatal("wrong difficulty")
86 return
87 }
88 
89 if h0.ExpiresAt != h3.ExpiresAt {
90 t.Fatal("wrong expiresat")
91 return
92 }
93 
94 if h0.Subject != h3.Subject {
95 t.Fatal("wrong subject")
96 return
97 }
98 
99 if h0.Nonce != h3.Nonce {
100 t.Fatal("wrong nonce")
101 return
102 }
103 
104 if h0.Alg != h3.Alg {
105 t.Fatal("wrong algorithm")
106 return
107 }
108 
109 if h0.Solution != h3.Solution {
110 t.Fatal("wrong solution")
111 return
112 }
113}
114 
115func TestExpired(t *testing.T) {
116 h := New(Hashcash{
117 Alg: "SHA-256",
118 Difficulty: 10,
119 ExpiresAt: time.Now().Add(-5 * time.Second),
120 })
121 
122 err := h.Verify(h.Subject)
123 if nil == err {
124 t.Error("verified expired token")
125 return
126 }
127 if err != ErrExpired {
128 t.Error("expired token error is not ErrExpired")
129 return
130 }
131}
132 
133func TestNoExpiry(t *testing.T) {
134 h := New(Hashcash{})
135 h.ExpiresAt = time.Time{}
136 
137 if err := h.Solve(20); nil != err {
138 t.Error(err)
139 return
140 }
141 
142 if err := h.Verify(h.Subject); nil != err {
143 t.Error(err)
144 return
145 }
146}
147 
148func TestSolve0(t *testing.T) {
149 h := New(Hashcash{
150 ExpiresAt: never,
151 Nonce: "DeadBeef",
152 })
153 h.Difficulty = 0
154 
155 if err := h.Solve(1); nil != err {
156 t.Error(err)
157 return
158 }
159 
160 if err := h.Verify(h.Subject); nil != err {
161 t.Error(err)
162 return
163 }
164}
165 
166func TestSolve1(t *testing.T) {
167 h := New(Hashcash{
168 Difficulty: 1,
169 ExpiresAt: never,
170 Nonce: "DeadBeef",
171 })
172 
173 if err := h.Solve(2); nil != err {
174 t.Error(err)
175 return
176 }
177 
178 if err := h.Verify(h.Subject); nil != err {
179 t.Error(err)
180 return
181 }
182}
183 
184func TestSolve2(t *testing.T) {
185 h := New(Hashcash{
186 Difficulty: 2,
187 ExpiresAt: never,
188 Nonce: "DeadBeef",
189 })
190 
191 if err := h.Solve(3); nil != err {
192 t.Error(err)
193 return
194 }
195 
196 if err := h.Verify(h.Subject); nil != err {
197 t.Error(err)
198 return
199 }
200}
201 
202func TestSolve7(t *testing.T) {
203 h := New(Hashcash{
204 Difficulty: 7,
205 ExpiresAt: never,
206 Nonce: "DeadBeef",
207 })
208 
209 if err := h.Solve(8); nil != err {
210 t.Error(err)
211 return
212 }
213 
214 if err := h.Verify(h.Subject); nil != err {
215 t.Error(err)
216 return
217 }
218}
219 
220func TestSolve8(t *testing.T) {
221 h := New(Hashcash{
222 Difficulty: 8,
223 ExpiresAt: never,
224 Nonce: "DeadBeef",
225 })
226 
227 if err := h.Solve(9); nil != err {
228 t.Error(err)
229 return
230 }
231 
232 if err := h.Verify(h.Subject); nil != err {
233 t.Error(err)
234 return
235 }
236}
237 
238func TestSolve9(t *testing.T) {
239 h := New(Hashcash{
240 Difficulty: 9,
241 ExpiresAt: never,
242 Nonce: "DeadBeef",
243 })
244 
245 if err := h.Solve(10); nil != err {
246 t.Error(err)
247 return
248 }
249 
250 if err := h.Verify(h.Subject); nil != err {
251 t.Error(err)
252 return
253 }
254}
255 
256func TestSolve15(t *testing.T) {
257 h := New(Hashcash{
258 Difficulty: 15,
259 ExpiresAt: never,
260 Nonce: "DeadBeef",
261 })
262 
263 if err := h.Solve(16); nil != err {
264 t.Error(err)
265 return
266 }
267 
268 if err := h.Verify(h.Subject); nil != err {
269 t.Error(err)
270 return
271 }
272}
273 
274func TestSolve16(t *testing.T) {
275 h := New(Hashcash{
276 Difficulty: 16,
277 ExpiresAt: never,
278 Nonce: "DeadBeef",
279 })
280 
281 if err := h.Solve(17); nil != err {
282 t.Error(err)
283 return
284 }
285 
286 if err := h.Verify(h.Subject); nil != err {
287 t.Error(err)
288 return
289 }
290}
291 
292func TestSolve17(t *testing.T) {
293 h := New(Hashcash{
294 Difficulty: 17,
295 ExpiresAt: never,
296 Nonce: "DeadBeef",
297 })
298 
299 if err := h.Solve(18); nil != err {
300 t.Error(err)
301 return
302 }
303 
304 if err := h.Verify(h.Subject); nil != err {
305 t.Error(err)
306 return
307 }
308 
309 if "H:17:32693036645:*:DeadBeef:SHA-256:R7sIAA" != h.String() {
310 t.Errorf("unexpected hashcash string: %s, has the implementation changed?", h.String())
311 }
312}
313 
314func TestTooHard(t *testing.T) {
315 h := New(Hashcash{
316 Alg: "SHA-256",
317 Difficulty: 24,
318 ExpiresAt: never,
319 Nonce: "DeadBeef",
320 })
321 
322 err := h.Solve(20)
323 if nil == err {
324 t.Error(errors.New("the challenge is too hard, should've quite"))
325 return
326 }
327 if ErrInvalidDifficulty != err {
328 t.Error(errors.New("incorrect error"))
329 return
330 }
331}