Comparison

util/jwt.lua @ 12699:b3d0c1457584

util.jwt: Add support for RSA-based algorithms (RS256, PS256)
author Matthew Wild <mwild1@gmail.com>
date Sat, 02 Jul 2022 12:26:43 +0100
parent 12696:27a72982e331
child 12702:f63176781940
comparison
equal deleted inserted replaced
12698:999663b4e39d 12699:b3d0c1457584
64 end 64 end
65 65
66 return { sign = sign, verify = verify, load_key = load_key }; 66 return { sign = sign, verify = verify, load_key = load_key };
67 end 67 end
68 68
69 -- ES*** family 69 local function new_crypto_algorithm(name, key_type, c_sign, c_verify, sig_encode, sig_decode)
70 local function new_ecdsa_algorithm(name, c_sign, c_verify)
71 local static_header = new_static_header(name); 70 local static_header = new_static_header(name);
72 71
73 return { 72 return {
74 sign = function (private_key, payload) 73 sign = function (private_key, payload)
75 local encoded_payload = json.encode(payload); 74 local encoded_payload = json.encode(payload);
76 local signed = static_header .. b64url(encoded_payload); 75 local signed = static_header .. b64url(encoded_payload);
77 76
78 local der_sig = c_sign(private_key, signed); 77 local signature = c_sign(private_key, signed);
78 if sig_encode then
79 signature = sig_encode(signature);
80 end
79 81
80 local r, s = crypto.parse_ecdsa_signature(der_sig); 82 return signed.."."..b64url(signature);
81
82 return signed.."."..b64url(r..s);
83 end; 83 end;
84 84
85 verify = function (public_key, blob) 85 verify = function (public_key, blob)
86 local signed, signature, raw_payload = decode_jwt(blob, name); 86 local signed, signature, raw_payload = decode_jwt(blob, name);
87 if not signed then return nil, signature; end -- nil, err 87 if not signed then return nil, signature; end -- nil, err
88 88
89 local raw_signature = unb64url(signature); 89 signature = unb64url(signature);
90 90 if sig_decode and signature then
91 local der_sig = crypto.build_ecdsa_signature(raw_signature:sub(1, 32), raw_signature:sub(33, 64)); 91 signature = sig_decode(signature);
92 if not der_sig then 92 end
93 if not signature then
93 return false, "signature-mismatch"; 94 return false, "signature-mismatch";
94 end 95 end
95 96
96 local verify_ok = c_verify(public_key, signed, der_sig); 97 local verify_ok = c_verify(public_key, signed, signature);
97 if not verify_ok then 98 if not verify_ok then
98 return false, "signature-mismatch"; 99 return false, "signature-mismatch";
99 end 100 end
100 101
101 local payload, err = json.decode(unb64url(raw_payload)); 102 local payload, err = json.decode(unb64url(raw_payload));
106 return true, payload; 107 return true, payload;
107 end; 108 end;
108 109
109 load_public_key = function (public_key_pem) 110 load_public_key = function (public_key_pem)
110 local key = assert(crypto.import_public_pem(public_key_pem)); 111 local key = assert(crypto.import_public_pem(public_key_pem));
111 assert(key:get_type() == "id-ecPublicKey", "incorrect key type"); 112 assert(key:get_type() == key_type, "incorrect key type");
112 return key; 113 return key;
113 end; 114 end;
114 115
115 load_private_key = function (private_key_pem) 116 load_private_key = function (private_key_pem)
116 local key = assert(crypto.import_private_pem(private_key_pem)); 117 local key = assert(crypto.import_private_pem(private_key_pem));
117 assert(key:get_type() == "id-ecPublicKey", "incorrect key type"); 118 assert(key:get_type() == key_type, "incorrect key type");
118 return key; 119 return key;
119 end; 120 end;
120 }; 121 };
121 end 122 end
122 123
124 -- RS***, PS***
125 local function new_rsa_algorithm(name, c_sign, c_verify)
126 return new_crypto_algorithm(name, "rsaEncryption", c_sign, c_verify);
127 end
128
129 -- ES***
130 local function new_ecdsa_algorithm(name, c_sign, c_verify)
131 local function encode_ecdsa_sig(der_sig)
132 local r, s = crypto.parse_ecdsa_signature(der_sig);
133 return r..s;
134 end
135
136 local function decode_ecdsa_sig(jwk_sig)
137 return crypto.build_ecdsa_signature(jwk_sig:sub(1, 32), jwk_sig:sub(33, 64));
138 end
139 return new_crypto_algorithm(name, "id-ecPublicKey", c_sign, c_verify, encode_ecdsa_sig, decode_ecdsa_sig);
140 end
141
123 local algorithms = { 142 local algorithms = {
124 HS256 = new_hmac_algorithm("HS256", hashes.hmac_sha256); 143 HS256 = new_hmac_algorithm("HS256", hashes.hmac_sha256);
125 ES256 = new_ecdsa_algorithm("ES256", crypto.ecdsa_sha256_sign, crypto.ecdsa_sha256_verify); 144 ES256 = new_ecdsa_algorithm("ES256", crypto.ecdsa_sha256_sign, crypto.ecdsa_sha256_verify);
145 RS256 = new_rsa_algorithm("RS256", crypto.rsassa_pkcs1_256_sign, crypto.rsassa_pkcs1_256_verify);
146 PS256 = new_rsa_algorithm("PS256", crypto.rsassa_pss_256_sign, crypto.rsassa_pss_256_verify);
126 }; 147 };
127 148
128 local function new_signer(algorithm, key_input) 149 local function new_signer(algorithm, key_input)
129 local impl = assert(algorithms[algorithm], "Unknown JWT algorithm: "..algorithm); 150 local impl = assert(algorithms[algorithm], "Unknown JWT algorithm: "..algorithm);
130 local key = (impl.load_private_key or impl.load_key)(key_input); 151 local key = (impl.load_private_key or impl.load_key)(key_input);