author | Kim Alvefur <zash@zash.se> |
Sat, 02 Mar 2024 14:14:27 +0100 | |
changeset 13459 | 2a001cd7f99a |
parent 12979 | d10957394a3c |
permissions | -rw-r--r-- |
12979
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
diff
changeset
|
1 |
local crypto = require "prosody.util.crypto"; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
diff
changeset
|
2 |
local json = require "prosody.util.json"; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
diff
changeset
|
3 |
local hashes = require "prosody.util.hashes"; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
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:
12844
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:
12844
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:
12844
diff
changeset
|
7 |
local bit = require "prosody.util.bitcompat"; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
diff
changeset
|
8 |
local hex = require "prosody.util.hex"; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
diff
changeset
|
9 |
local rand = require "prosody.util.random"; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12844
diff
changeset
|
10 |
local s_pack = require "prosody.util.struct".pack; |
12698
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 |
12842
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
20 |
|
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
21 |
local valid_tails = { |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
22 |
nil; -- Always invalid |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
23 |
"^.[AQgw]$"; -- b??????00 |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
24 |
"^..[AQgwEUk0IYo4Mcs8]$"; -- b????0000 |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
25 |
} |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
26 |
|
12698
26a004c96ef8
util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
27 |
local function unb64url(data) |
12842
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
28 |
local rem = #data%4; |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
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:
12720
diff
changeset
|
30 |
return nil; |
2e71b76ac299
util.paseto: Stricter base64 decoding, as per spec
Matthew Wild <mwild1@gmail.com>
parents:
12720
diff
changeset
|
31 |
end |
12698
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) |
12720
0b68b021ce46
util.paseto: Do strict type check in pae() function
Kim Alvefur <zash@zash.se>
parents:
12717
diff
changeset
|
40 |
if type(parts) ~= "table" then |
0b68b021ce46
util.paseto: Do strict type check in pae() function
Kim Alvefur <zash@zash.se>
parents:
12717
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:
12717
diff
changeset
|
42 |
end |
12698
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 "" }); |
12717
52eead170bb8
util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents:
12715
diff
changeset
|
57 |
local sig = crypto.ed25519_sign(sk, m2); |
12698
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 |
12713
b3f7c77c1f08
util.paseto: Fix to decode footer before comparison
Matthew Wild <mwild1@gmail.com>
parents:
12698
diff
changeset
|
70 |
f = f and unb64url(f) or nil; |
12698
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 "" }); |
12717
52eead170bb8
util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents:
12715
diff
changeset
|
82 |
local ok = crypto.ed25519_verify(pk, m2, s); |
12698
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 |
|
12717
52eead170bb8
util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents:
12715
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:
12715
diff
changeset
|
94 |
v4_public.import_public_key = crypto.import_public_pem; |
12698
26a004c96ef8
util.paseto: Implementation of PASETO v4.public tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
95 |
function v4_public.new_keypair() |
12717
52eead170bb8
util.paseto: Drop custom wrappers around key objects
Matthew Wild <mwild1@gmail.com>
parents:
12715
diff
changeset
|
96 |
return crypto.generate_ed25519_keypair(); |
12698
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 |
|
12715
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
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:
12714
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:
12714
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:
12714
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:
12714
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:
12714
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:
12714
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:
12714
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:
12714
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:
12714
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:
12714
diff
changeset
|
109 |
end; |
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
diff
changeset
|
110 |
end |
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
diff
changeset
|
111 |
|
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
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:
12714
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:
12714
diff
changeset
|
114 |
end |
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
diff
changeset
|
115 |
|
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
diff
changeset
|
116 |
function v4_public.new_verifier(public_key_pem, options) |
12843
7db1c1da7bfd
util.paseto: Fix omitted parameter
Matthew Wild <mwild1@gmail.com>
parents:
12842
diff
changeset
|
117 |
return (select(2, v4_public.init(nil, public_key_pem, options))); |
12715
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
diff
changeset
|
118 |
end |
9e9f158d6699
util.paseto: Export similar API to new util.jwt for ease and consistency
Matthew Wild <mwild1@gmail.com>
parents:
12714
diff
changeset
|
119 |
|
12844
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
120 |
local v3_local = { _key_mt = {} }; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
121 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
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:
12843
diff
changeset
|
124 |
local Ek = tmp:sub(1, 32); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
125 |
local n2 = tmp:sub(33); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
127 |
return Ek, Ak, n2; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
128 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
129 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
131 |
assert(#k == 32) |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
132 |
if type(m) ~= "table" then |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
134 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
135 |
m = json.encode(m); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
136 |
local h = "v3.local."; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
137 |
local n = rand.bytes(32); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
139 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
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:
12843
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:
12843
diff
changeset
|
143 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
144 |
if not f or f == "" then |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
145 |
return h..b64url(n..c..t); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
146 |
else |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
148 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
149 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
150 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
152 |
assert(#k == 32) |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
153 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
155 |
if not h then |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
156 |
return nil, "invalid-token-format"; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
157 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
159 |
if expected_f then |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
161 |
return nil, "invalid-footer"; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
162 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
163 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
164 |
local m = unb64url(sm); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
166 |
return nil, "invalid-token-format"; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
167 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
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:
12843
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:
12843
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:
12843
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:
12843
diff
changeset
|
173 |
return nil, "invalid-token"; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
174 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
176 |
if not m2 then |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
177 |
return nil, "invalid-token"; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
178 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
179 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
180 |
local payload, err = json.decode(m2); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
182 |
return nil, "json-decode-error"; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
183 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
184 |
return payload; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
185 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
186 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
187 |
function v3_local.new_key() |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
189 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
190 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
191 |
function v3_local.init(key, options) |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
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:
12843
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:
12843
diff
changeset
|
195 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
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:
12843
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:
12843
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:
12843
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:
12843
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:
12843
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:
12843
diff
changeset
|
203 |
end; |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
204 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
205 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
diff
changeset
|
207 |
return (v3_local.init(key, options)); |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
208 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
209 |
|
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
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:
12843
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:
12843
diff
changeset
|
212 |
end |
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
213 |
|
12698
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; |
12844
33d902b093f0
util.paseto: Add support for v3.local tokens
Matthew Wild <mwild1@gmail.com>
parents:
12843
diff
changeset
|
216 |
v3_local = v3_local; |
12698
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 |
}; |