Tue, 09 Mar 2021 12:16:56 +0000
Initial commit
0 | 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 | }; |