Annotate

util/paseto.lua @ 13028:b2e6a175537d

mod_debug_reset: Don't delay operations until next tick For some unknown reason, this was required with the old mock util.time functions prior to 012d6e7b723a. After 012d6e7b723a, it breaks. So I'm happy to revert to not delaying anything. This makes tests pass again.
author Matthew Wild <mwild1@gmail.com>
date Thu, 06 Apr 2023 14:17:50 +0100
parent 12975:d10957394a3c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12975
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
1 local crypto = require "prosody.util.crypto";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
2 local json = require "prosody.util.json";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
3 local hashes = require "prosody.util.hashes";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
4 local base64_encode = require "prosody.util.encodings".base64.encode;
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
5 local base64_decode = require "prosody.util.encodings".base64.decode;
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
6 local secure_equals = require "prosody.util.hashes".equals;
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
7 local bit = require "prosody.util.bitcompat";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
8 local hex = require "prosody.util.hex";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
9 local rand = require "prosody.util.random";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12840
diff changeset
10 local s_pack = require "prosody.util.struct".pack;
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 local s_gsub = string.gsub;
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 local v4_public = {};
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 local b64url_rep = { ["+"] = "-", ["/"] = "_", ["="] = "", ["-"] = "+", ["_"] = "/" };
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 local function b64url(data)
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 return (s_gsub(base64_encode(data), "[+/=]", b64url_rep));
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 end
12838
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
20
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
21 local valid_tails = {
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
22 nil; -- Always invalid
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
23 "^.[AQgw]$"; -- b??????00
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
24 "^..[AQgwEUk0IYo4Mcs8]$"; -- b????0000
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
25 }
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
26
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 local function unb64url(data)
12838
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
28 local rem = #data%4;
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
29 if data:sub(-1,-1) == "=" or rem == 1 or (rem > 1 and not data:sub(-rem):match(valid_tails[rem])) then
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
30 return nil;
2e71b76ac299 util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents: 12716
diff changeset
31 end
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 return base64_decode(s_gsub(data, "[-_]", b64url_rep).."==");
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 local function le64(n)
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 return s_pack("<I8", bit.band(n, 0x7F));
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 local function pae(parts)
12716
0b68b021ce46 util.paseto: Do strict type check in pae() function
Kim Alvefur <zash@zash.se>
parents: 12713
diff changeset
40 if type(parts) ~= "table" then
0b68b021ce46 util.paseto: Do strict type check in pae() function
Kim Alvefur <zash@zash.se>
parents: 12713
diff changeset
41 error("bad argument #1 to 'pae' (table expected, got "..type(parts)..")");
0b68b021ce46 util.paseto: Do strict type check in pae() function
Kim Alvefur <zash@zash.se>
parents: 12713
diff changeset
42 end
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 local o = { le64(#parts) };
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 for _, part in ipairs(parts) do
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 table.insert(o, le64(#part)..part);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 return table.concat(o);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 function v4_public.sign(m, sk, f, i)
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 if type(m) ~= "table" then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 return nil, "PASETO payloads must be a table";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 m = json.encode(m);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 local h = "v4.public.";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 local m2 = pae({ h, m, f or "", i or "" });
12713
52eead170bb8 util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents: 12711
diff changeset
57 local sig = crypto.ed25519_sign(sk, m2);
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 if not f or f == "" then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 return h..b64url(m..sig);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 else
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 return h..b64url(m..sig).."."..b64url(f);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 function v4_public.verify(tok, pk, expected_f, i)
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 local h, sm, f = tok:match("^(v4%.public%.)([^%.]+)%.?(.*)$");
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 if not h then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 return nil, "invalid-token-format";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 end
12709
b3f7c77c1f08 util.paseto: Fix to decode footer before comparison
Matthew Wild <mwild1@gmail.com>
parents: 12694
diff changeset
70 f = f and unb64url(f) or nil;
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 if expected_f then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 if not f or not secure_equals(expected_f, f) then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 return nil, "invalid-footer";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 local raw_sm = unb64url(sm);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 if not raw_sm or #raw_sm <= 64 then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 return nil, "invalid-token-format";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 local s, m = raw_sm:sub(-64), raw_sm:sub(1, -65);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 local m2 = pae({ h, m, f or "", i or "" });
12713
52eead170bb8 util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents: 12711
diff changeset
82 local ok = crypto.ed25519_verify(pk, m2, s);
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 if not ok then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 return nil, "invalid-token";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 local payload, err = json.decode(m);
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 if err ~= nil or type(payload) ~= "table" then
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 return nil, "json-decode-error";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 return payload;
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92
12713
52eead170bb8 util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents: 12711
diff changeset
93 v4_public.import_private_key = crypto.import_private_pem;
52eead170bb8 util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents: 12711
diff changeset
94 v4_public.import_public_key = crypto.import_public_pem;
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 function v4_public.new_keypair()
12713
52eead170bb8 util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents: 12711
diff changeset
96 return crypto.generate_ed25519_keypair();
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 end
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98
12711
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
99 function v4_public.init(private_key_pem, public_key_pem, options)
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
100 local sign, verify = v4_public.sign, v4_public.verify;
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
101 local public_key = public_key_pem and v4_public.import_public_key(public_key_pem);
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
102 local private_key = private_key_pem and v4_public.import_private_key(private_key_pem);
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
103 local default_footer = options and options.default_footer;
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
104 local default_assertion = options and options.default_implicit_assertion;
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
105 return private_key and function (token, token_footer, token_assertion)
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
106 return sign(token, private_key, token_footer or default_footer, token_assertion or default_assertion);
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
107 end, public_key and function (token, expected_footer, token_assertion)
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
108 return verify(token, public_key, expected_footer or default_footer, token_assertion or default_assertion);
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
109 end;
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
110 end
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
111
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
112 function v4_public.new_signer(private_key_pem, options)
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
113 return (v4_public.init(private_key_pem, nil, options));
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
114 end
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
115
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
116 function v4_public.new_verifier(public_key_pem, options)
12839
7db1c1da7bfd util.paseto: Fix omitted parameter
Matthew Wild <mwild1@gmail.com>
parents: 12838
diff changeset
117 return (select(2, v4_public.init(nil, public_key_pem, options)));
12711
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
118 end
9e9f158d6699 util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents: 12710
diff changeset
119
12840
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
120 local v3_local = { _key_mt = {} };
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
121
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
122 local function v3_local_derive_keys(k, n)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
123 local tmp = hashes.hkdf_hmac_sha384(48, k, nil, "paseto-encryption-key"..n);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
124 local Ek = tmp:sub(1, 32);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
125 local n2 = tmp:sub(33);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
126 local Ak = hashes.hkdf_hmac_sha384(48, k, nil, "paseto-auth-key-for-aead"..n);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
127 return Ek, Ak, n2;
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
128 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
129
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
130 function v3_local.encrypt(m, k, f, i)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
131 assert(#k == 32)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
132 if type(m) ~= "table" then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
133 return nil, "PASETO payloads must be a table";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
134 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
135 m = json.encode(m);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
136 local h = "v3.local.";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
137 local n = rand.bytes(32);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
138 local Ek, Ak, n2 = v3_local_derive_keys(k, n);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
139
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
140 local c = crypto.aes_256_ctr_encrypt(Ek, n2, m);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
141 local m2 = pae({ h, n, c, f or "", i or "" });
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
142 local t = hashes.hmac_sha384(Ak, m2);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
143
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
144 if not f or f == "" then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
145 return h..b64url(n..c..t);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
146 else
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
147 return h..b64url(n..c..t).."."..b64url(f);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
148 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
149 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
150
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
151 function v3_local.decrypt(tok, k, expected_f, i)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
152 assert(#k == 32)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
153
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
154 local h, sm, f = tok:match("^(v3%.local%.)([^%.]+)%.?(.*)$");
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
155 if not h then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
156 return nil, "invalid-token-format";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
157 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
158 f = f and unb64url(f) or nil;
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
159 if expected_f then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
160 if not f or not secure_equals(expected_f, f) then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
161 return nil, "invalid-footer";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
162 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
163 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
164 local m = unb64url(sm);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
165 if not m or #m <= 80 then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
166 return nil, "invalid-token-format";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
167 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
168 local n, c, t = m:sub(1, 32), m:sub(33, -49), m:sub(-48);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
169 local Ek, Ak, n2 = v3_local_derive_keys(k, n);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
170 local preAuth = pae({ h, n, c, f or "", i or "" });
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
171 local t2 = hashes.hmac_sha384(Ak, preAuth);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
172 if not secure_equals(t, t2) then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
173 return nil, "invalid-token";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
174 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
175 local m2 = crypto.aes_256_ctr_decrypt(Ek, n2, c);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
176 if not m2 then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
177 return nil, "invalid-token";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
178 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
179
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
180 local payload, err = json.decode(m2);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
181 if err ~= nil or type(payload) ~= "table" then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
182 return nil, "json-decode-error";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
183 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
184 return payload;
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
185 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
186
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
187 function v3_local.new_key()
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
188 return "secret-token:paseto.v3.local:"..hex.encode(rand.bytes(32));
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
189 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
190
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
191 function v3_local.init(key, options)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
192 local encoded_key = key:match("^secret%-token:paseto%.v3%.local:(%x+)$");
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
193 if not encoded_key or #encoded_key ~= 64 then
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
194 return error("invalid key for v3.local");
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
195 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
196 local raw_key = hex.decode(encoded_key);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
197 local default_footer = options and options.default_footer;
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
198 local default_assertion = options and options.default_implicit_assertion;
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
199 return function (token, token_footer, token_assertion)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
200 return v3_local.encrypt(token, raw_key, token_footer or default_footer, token_assertion or default_assertion);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
201 end, function (token, token_footer, token_assertion)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
202 return v3_local.decrypt(token, raw_key, token_footer or default_footer, token_assertion or default_assertion);
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
203 end;
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
204 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
205
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
206 function v3_local.new_signer(key, options)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
207 return (v3_local.init(key, options));
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
208 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
209
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
210 function v3_local.new_verifier(key, options)
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
211 return (select(2, v3_local.init(key, options)));
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
212 end
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
213
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
214 return {
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
215 pae = pae;
12840
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
216 v3_local = v3_local;
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
217 v4_public = v4_public;
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
218 };