MINOR: jws: emit the JWK thumbprint

jwk_thumbprint() is a function which is a function which implements
RFC7368 and emits a JWK thumbprint using a EVP_PKEY.

EVP_PKEY_EC_to_pub_jwk() and EVP_PKEY_RSA_to_pub_jwk() were changed in
order to match what is required to emit a thumbprint (ie, no spaces or
lines and the lexicographic order of the fields)
This commit is contained in:
William Lallemand 2025-03-25 15:21:50 +01:00
parent ed1d4807da
commit f8fe84caca
2 changed files with 52 additions and 13 deletions

View File

@ -13,5 +13,6 @@ int jws_b64_payload(char *payload, char *dst, size_t dsize);
int jws_b64_protected(enum jwt_alg alg, char *kid, char *jwk, char *nonce, char *url, char *dst, size_t dsize); int jws_b64_protected(enum jwt_alg alg, char *kid, char *jwk, char *nonce, char *url, char *dst, size_t dsize);
int jws_b64_signature(EVP_PKEY *pkey, enum jwt_alg alg, char *b64protected, char *b64payload, char *dst, size_t dsize); int jws_b64_signature(EVP_PKEY *pkey, enum jwt_alg alg, char *b64protected, char *b64payload, char *dst, size_t dsize);
int jws_flattened(char *protected, char *payload, char *signature, char *dst, size_t dsize); int jws_flattened(char *protected, char *payload, char *signature, char *dst, size_t dsize);
int jws_thumbprint(EVP_PKEY *pkey, char *dst, size_t dsize);
#endif /* ! _HAPROXY_JWK_H_ */ #endif /* ! _HAPROXY_JWK_H_ */

View File

@ -148,13 +148,13 @@ static int EVP_PKEY_EC_to_pub_jwk(EVP_PKEY *pkey, char *dst, size_t dsize)
if (str_x->data == 0 || str_y->data == 0) if (str_x->data == 0 || str_y->data == 0)
goto out; goto out;
ret = snprintf(dst, dsize, "{\n" ret = snprintf(dst, dsize, "{"
" \"kty\": \"%s\",\n" "\"crv\":\"%s\","
" \"crv\": \"%s\",\n" "\"kty\":\"%s\","
" \"x\": \"%s\",\n" "\"x\":\"%s\","
" \"y\": \"%s\"\n" "\"y\":\"%s\""
"}\n", "}",
"EC", crv, str_x->area, str_y->area); crv, "EC", str_x->area, str_y->area);
if (ret >= dsize) if (ret >= dsize)
ret = 0; ret = 0;
@ -209,12 +209,12 @@ static int EVP_PKEY_RSA_to_pub_jwk(EVP_PKEY *pkey, char *dst, size_t dsize)
if (str_n->data == 0 || str_e->data == 0) if (str_n->data == 0 || str_e->data == 0)
goto out; goto out;
ret = snprintf(dst, dsize, "{\n" ret = snprintf(dst, dsize, "{"
" \"kty\": \"%s\",\n" "\"e\":\"%s\","
" \"n\": \"%s\",\n" "\"kty\":\"%s\","
" \"e\": \"%s\"\n" "\"n\":\"%s\""
"}\n", "}",
"RSA", str_n->area, str_e->area); str_e->area, "RSA", str_n->area );
if (ret >= dsize) if (ret >= dsize)
ret = 0; ret = 0;
@ -486,6 +486,44 @@ out:
} }
/*
* Fill a <dst> buffer of <dsize> size with a jwk thumbprint from a pkey
*
* Return the size of the data or 0
*/
int jws_thumbprint(EVP_PKEY *pkey, char *dst, size_t dsize)
{
int ret = 0;
struct buffer *jwk = NULL;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int size;
if ((jwk = alloc_trash_chunk()) == NULL)
goto out;
switch (EVP_PKEY_base_id(pkey)) {
case EVP_PKEY_RSA:
jwk->data = EVP_PKEY_RSA_to_pub_jwk(pkey, jwk->area, jwk->size);
break;
case EVP_PKEY_EC:
jwk->data = EVP_PKEY_EC_to_pub_jwk(pkey, jwk->area, jwk->size);
break;
default:
break;
}
if (EVP_Digest(jwk->area, jwk->data, md, &size, EVP_sha256(), NULL) == 0)
goto out;
ret = a2base64url((const char *)md, size, dst, dsize);
out:
free_trash_chunk(jwk);
return ret;
}
int jws_flattened(char *protected, char *payload, char *signature, char *dst, size_t dsize) int jws_flattened(char *protected, char *payload, char *signature, char *dst, size_t dsize)
{ {
int ret = 0; int ret = 0;