|
1 local hmac_sha256 = require"util.hashes".hmac_sha256; |
|
2 local base64_encode = require"util.encodings".base64.encode; |
|
3 local base64_decode = require"util.encodings".base64.decode; |
|
4 local datetime = require"util.datetime"; |
|
5 local t_insert = table.insert; |
|
6 |
|
7 local function generate(user, expires, key) |
|
8 local data = ("%s %s"):format(datetime.date(expires), user); |
|
9 local signature = hmac_sha256(key, data); |
|
10 return base64_encode(data .. signature); |
|
11 end |
|
12 |
|
13 local function verify(cookie, key) |
|
14 if not cookie then |
|
15 return nil, "no value"; |
|
16 end |
|
17 cookie = base64_decode(cookie); |
|
18 if not cookie then |
|
19 return nil, "invalid armor"; |
|
20 end |
|
21 local data = cookie:sub(1, -33) |
|
22 if cookie:sub(-32) ~= hmac_sha256(key, data) then |
|
23 return nil, "invalid signature"; |
|
24 end |
|
25 if data < datetime.date() then |
|
26 return nil, "expired"; |
|
27 end |
|
28 return data:sub(12); -- Strip date |
|
29 end |
|
30 |
|
31 local function cookiedecode(s) |
|
32 local r = {}; |
|
33 if not s then return r; end |
|
34 for k, v in s:gmatch("([%w!#$%%&'*+%-.^_`|~]+)=\"?([%w!#-+--/:<-@%]-`_]+)\"?") do |
|
35 r[k] = v; |
|
36 t_insert(r, { name = k, value = v }); |
|
37 end |
|
38 return r; |
|
39 end |
|
40 |
|
41 return { |
|
42 decode = cookiedecode; |
|
43 generate = generate; |
|
44 verify = verify; |
|
45 }; |