Annotate

util/paseto.lua @ 12843:e609e10966f5

Merge 0.12->trunk
author Kim Alvefur <zash@zash.se>
date Sat, 14 Jan 2023 14:09:33 +0100
parent 12840:33d902b093f0
child 12975:d10957394a3c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local crypto = require "util.crypto";
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 local json = require "util.json";
12840
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
3 local hashes = require "util.hashes";
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 local base64_encode = require "util.encodings".base64.encode;
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 local base64_decode = require "util.encodings".base64.decode;
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 local secure_equals = require "util.hashes".equals;
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 local bit = require "util.bitcompat";
12840
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
8 local hex = require "util.hex";
33d902b093f0 util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents: 12839
diff changeset
9 local rand = require "util.random";
12694
26a004c96ef8 util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 local s_pack = require "util.struct".pack;
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 };