@@ -2211,8 +2211,10 @@ jwk_set_t *jwks_create_fromurl(const char *url, int verify);
22112211 */
22122212typedef enum {
22132213 JWK_KEY_NONE = 0x0000 , /**< No options */
2214- JWK_KEY_GEN_KID = 0x0001 , /**< Generate a random (uuidv4)
2215- "kid" for each imported key */
2214+ JWK_KEY_GEN_KID = 0x0001 , /**< Generate a deterministic
2215+ "kid" (the @rfc{7638} JWK
2216+ SHA-256 thumbprint) for each
2217+ imported key */
22162218 JWK_KEY_TRY_HMAC = 0x0002 , /**< If the input does not parse
22172219 as a PEM/DER key, treat the
22182220 raw bytes as an "oct" (HMAC)
@@ -2553,6 +2555,103 @@ char *jwks_item_export(const jwk_item_t *item, int priv);
25532555JWT_EXPORT
25542556char * jwks_export (const jwk_set_t * jwk_set , int priv );
25552557
2558+ /**
2559+ * @brief Hash algorithm for a JWK Thumbprint
2560+ *
2561+ * Selects the digest used by jwks_item_thumbprint() and
2562+ * jwks_item_thumbprint_uri(). SHA-256 is the value 0, so it is the default for
2563+ * a zero-initialized argument and is what virtually all deployments use.
2564+ *
2565+ * @since 3.6.0
2566+ */
2567+ typedef enum {
2568+ JWK_THUMBPRINT_SHA256 = 0 , /**< SHA-256 (default) */
2569+ JWK_THUMBPRINT_SHA384 , /**< SHA-384 */
2570+ JWK_THUMBPRINT_SHA512 , /**< SHA-512 */
2571+ } jwk_thumbprint_alg_t ;
2572+
2573+ /**
2574+ * @brief Compute the JWK Thumbprint of a key
2575+ *
2576+ * @rfc{7638,3}
2577+ *
2578+ * Produces the base64url-encoded SHA-2 digest of the key's canonical JWK form:
2579+ * a JSON object containing only the members required for the key type, with no
2580+ * whitespace and the member names in lexicographic order. The result is a
2581+ * stable, deterministic fingerprint of the (public) key parameters, commonly
2582+ * used as a key id (@c "kid") or as the @c "jkt" confirmation value.
2583+ *
2584+ * The thumbprint is computed over public parameters and is identical whether
2585+ * the item was loaded from a JWK or from a PEM/DER key.
2586+ *
2587+ * @param item A JWK Item
2588+ * @param alg The thumbprint hash algorithm (see @ref jwk_thumbprint_alg_t);
2589+ * @ref JWK_THUMBPRINT_SHA256 is the default.
2590+ * @return A newly allocated, nil-terminated base64url string the caller must
2591+ * free with free(), or NULL on error (an unusable key, a missing required
2592+ * member, or an invalid @p alg).
2593+ * @since 3.6.0
2594+ */
2595+ JWT_EXPORT
2596+ char * jwks_item_thumbprint (const jwk_item_t * item , jwk_thumbprint_alg_t alg );
2597+
2598+ /**
2599+ * @brief Compute the JWK Thumbprint URI of a key
2600+ *
2601+ * @rfc{9278}
2602+ *
2603+ * As jwks_item_thumbprint(), but returns the RFC 9278 URI form:
2604+ * @c "urn:ietf:params:oauth:jwk-thumbprint:sha-256:<thumbprint>" (or
2605+ * @c sha-384 / @c sha-512 to match @p alg).
2606+ *
2607+ * @param item A JWK Item
2608+ * @param alg The thumbprint hash algorithm (see @ref jwk_thumbprint_alg_t);
2609+ * @ref JWK_THUMBPRINT_SHA256 is the default.
2610+ * @return A newly allocated, nil-terminated URI string the caller must free
2611+ * with free(), or NULL on error.
2612+ * @since 3.6.0
2613+ */
2614+ JWT_EXPORT
2615+ char * jwks_item_thumbprint_uri (const jwk_item_t * item , jwk_thumbprint_alg_t alg );
2616+
2617+ /**
2618+ * @brief Find a key in a set by its JWK Thumbprint
2619+ *
2620+ * @rfc{7638}
2621+ *
2622+ * Returns the first item in @p jwk_set whose thumbprint (for the given hash)
2623+ * equals @p thumbprint. Unlike jwks_find_bykid(), this matches on the key's
2624+ * canonical, deterministic identity rather than the advisory @c "kid", so it
2625+ * works even when keys carry no (or an inconsistent) @c "kid" — e.g. matching a
2626+ * proof-of-possession @c "cnf"/@c "jkt" value against a set of known keys.
2627+ *
2628+ * @param jwk_set An existing jwk_set_t
2629+ * @param alg The hash used to produce @p thumbprint (see @ref jwk_thumbprint_alg_t)
2630+ * @param thumbprint A base64url JWK thumbprint, as from jwks_item_thumbprint()
2631+ * @return The matching jwk_item_t, or NULL if none matches or on bad input
2632+ * @since 3.6.0
2633+ */
2634+ JWT_EXPORT
2635+ jwk_item_t * jwks_find_bythumbprint (jwk_set_t * jwk_set , jwk_thumbprint_alg_t alg ,
2636+ const char * thumbprint );
2637+
2638+ /**
2639+ * @brief Find a key in a set by its JWK Thumbprint URI
2640+ *
2641+ * @rfc{9278}
2642+ *
2643+ * As jwks_find_bythumbprint(), but takes the RFC 9278 URI form
2644+ * (@c "urn:ietf:params:oauth:jwk-thumbprint:sha-256:<thumbprint>"); the hash
2645+ * is taken from the URI's @c sha-NNN label.
2646+ *
2647+ * @param jwk_set An existing jwk_set_t
2648+ * @param uri A JWK Thumbprint URI, as from jwks_item_thumbprint_uri()
2649+ * @return The matching jwk_item_t, or NULL if none matches or on bad input
2650+ * @since 3.6.0
2651+ */
2652+ JWT_EXPORT
2653+ jwk_item_t * jwks_find_bythumbprint_uri (jwk_set_t * jwk_set , const char * uri );
2654+
25562655/**
25572656 * @brief Retrieve binary octet data of a key
25582657 *
0 commit comments