cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
jwt.c File Reference

HS256/ES256/EdDSA JWT signing, verification, and decoded-claims access helpers. More...

#include <cwist/security/jwt/jwt.h>
#include <cwist/core/mem/alloc.h>
#include <cwist/core/sstring/sstring.h>
#include <cwist/core/seq/seq.h>
#include <cjson/cJSON.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/bn.h>
#include <openssl/obj.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
Include dependency graph for jwt.c:

Go to the source code of this file.

Macros

#define CWIST_JWT_TIME_LEEWAY   300
 

Enumerations

enum  jwt_alg_t { JWT_ALG_HS256 , JWT_ALG_ES256 , JWT_ALG_ED25519 }
 

Functions

char * cwist_jwt_sign (const char *payload_json, const char *secret, long exp_seconds)
 Sign a JWT token with HMAC-SHA256.
 
char * cwist_jwt_sign_es256 (const char *payload_json, const char *pem_private_key, const char *kid, long exp_seconds)
 Sign a JWT token with ES256 (ECDSA over P-256 with SHA-256).
 
char * cwist_jwt_sign_ed25519 (const char *payload_json, const char *pem_private_key, const char *kid, long exp_seconds)
 Sign a JWT token with EdDSA (Ed25519, RFC 8037).
 
cwist_jwt_claims * cwist_jwt_verify (const char *token, const char *secret)
 Verify a JWT token and return the decoded claims.
 
cwist_jwt_claims * cwist_jwt_verify_es256 (const char *token, const char *pem_key)
 Verify an ES256-signed JWT token and return the decoded claims.
 
cwist_jwt_claims * cwist_jwt_verify_ed25519 (const char *token, const char *pem_key)
 Verify an Ed25519-signed JWT token and return the decoded claims.
 
const char * cwist_jwt_claims_get (const cwist_jwt_claims *claims, const char *key)
 Retrieve one string-valued claim from a verified JWT payload.
 
void cwist_jwt_claims_destroy (cwist_jwt_claims *claims)
 Destroy a verified claims object and its parsed JSON payload.
 
cwist_jwt_chunk_t * cwist_jwt_split_chunks (const char *token, uint16_t chunk_payload_size, size_t *out_count)
 Split a JWT token into sequenced transport chunks.
 
void cwist_jwt_chunks_free (cwist_jwt_chunk_t *chunks, size_t count)
 Free a chunk array produced by cwist_jwt_split_chunks() or cwist_jwt_sign_chunks().
 
char * cwist_jwt_join_chunks (const cwist_jwt_chunk_t *chunks, size_t count)
 Reassemble a JWT token from sequenced transport chunks.
 
cwist_jwt_chunk_t * cwist_jwt_sign_chunks (const char *payload_json, const char *secret, long exp_seconds, uint16_t chunk_payload_size, size_t *out_count)
 Sign a payload as an HS256 JWT and split it into sequenced transport chunks.
 
cwist_jwt_claims * cwist_jwt_verify_chunks (const cwist_jwt_chunk_t *chunks, size_t count, const char *secret)
 Reassemble sequenced chunks into a token, verify it, and return its claims.
 

Detailed Description

HS256/ES256/EdDSA JWT signing, verification, and decoded-claims access helpers.

Definition in file jwt.c.

Macro Definition Documentation

◆ CWIST_JWT_TIME_LEEWAY

#define CWIST_JWT_TIME_LEEWAY   300

Enumeration Type Documentation

◆ jwt_alg_t

Enumerator
JWT_ALG_HS256 
JWT_ALG_ES256 
JWT_ALG_ED25519 

Definition at line 165 of file jwt.c.

Function Documentation

◆ cwist_jwt_chunks_free()

void cwist_jwt_chunks_free ( cwist_jwt_chunk_t *  chunks,
size_t  count 
)

Free a chunk array produced by cwist_jwt_split_chunks() or cwist_jwt_sign_chunks().

Free chunk objects returned by cwist_jwt_split_chunks().

Parameters
chunksChunk array to free; NULL is accepted as a no-op.
countNumber of entries in chunks.

Definition at line 837 of file jwt.c.

References cap, count, and cwist_free().

◆ cwist_jwt_claims_destroy()

void cwist_jwt_claims_destroy ( cwist_jwt_claims *  claims)

Destroy a verified claims object and its parsed JSON payload.

Free a claims object.

Parameters
claimsClaims object to destroy.

Definition at line 779 of file jwt.c.

References cap, and cwist_free().

◆ cwist_jwt_claims_get()

const char * cwist_jwt_claims_get ( const cwist_jwt_claims *  claims,
const char *  key 
)

Retrieve one string-valued claim from a verified JWT payload.

Retrieve a claim value by key from decoded claims.

Parameters
claimsVerified claims object.
keyClaim name to retrieve.
Returns
Borrowed pointer to the claim string, or NULL when absent/non-string.

Definition at line 766 of file jwt.c.

References cap.

◆ cwist_jwt_join_chunks()

char * cwist_jwt_join_chunks ( const cwist_jwt_chunk_t *  chunks,
size_t  count 
)

Reassemble a JWT token from sequenced transport chunks.

Reassemble a JWT token from sequenced chunks.

Parameters
chunksArray of sequenced chunks, in any order accepted by the assembler.
countNumber of entries in chunks.
Returns
Heap-allocated null-terminated JWT string, or NULL when the chunk set is invalid/incomplete or assembly/allocation fails.

The caller owns the returned string and must free it with cwist_free().

Definition at line 852 of file jwt.c.

References cap, count, cwist_alloc(), cwist_seq_assembler_create(), cwist_seq_assembler_destroy(), cwist_seq_assembler_feed(), cwist_seq_assembler_get_data(), and cwist_seq_chunk_parse().

Referenced by cwist_jwt_verify_chunks().

◆ cwist_jwt_sign()

char * cwist_jwt_sign ( const char *  payload_json,
const char *  secret,
long  exp_seconds 
)

Sign a JWT token with HMAC-SHA256.

Parameters
payload_jsonJSON string for the payload (e.g. "{\"sub\":\"1\"}"). Standard claims like "exp" and "iat" are added automatically when exp_seconds is > 0. Supply them yourself if you need fine-grained control (pass exp_seconds = 0 in that case).
secretHMAC secret key (null-terminated).
exp_secondsSeconds until expiry from now. Pass 0 to skip automatic "exp" injection (you must include it in payload_json).
Returns
Heap-allocated null-terminated JWT string, or NULL on error. Caller must free with cwist_free().

Definition at line 620 of file jwt.c.

References cap, and JWT_ALG_HS256.

Referenced by cwist_jwt_sign_chunks().

◆ cwist_jwt_sign_chunks()

cwist_jwt_chunk_t * cwist_jwt_sign_chunks ( const char *  payload_json,
const char *  secret,
long  exp_seconds,
uint16_t  chunk_payload_size,
size_t *  out_count 
)

Sign a payload as an HS256 JWT and split it into sequenced transport chunks.

Sign a JWT and immediately split it into sequenced chunks.

Parameters
payload_jsonRaw payload JSON string to sign.
secretShared HS256 signing secret.
exp_secondsLifetime in seconds to add when the payload lacks exp/iat.
chunk_payload_sizeMaximum payload bytes per chunk; must be non-zero.
out_countSet to the number of chunks produced.
Returns
Heap-allocated chunk array, or NULL when signing or chunking fails.

Free the result with cwist_jwt_chunks_free().

Definition at line 897 of file jwt.c.

References cap, cwist_free(), cwist_jwt_sign(), and cwist_jwt_split_chunks().

◆ cwist_jwt_sign_ed25519()

char * cwist_jwt_sign_ed25519 ( const char *  payload_json,
const char *  pem_private_key,
const char *  kid,
long  exp_seconds 
)

Sign a JWT token with EdDSA (Ed25519, RFC 8037).

Like cwist_jwt_sign_es256() but with an Ed25519 PEM private key; the header declares "alg":"EdDSA".

Parameters
payload_jsonJSON string for the payload (see cwist_jwt_sign()).
pem_private_keyPEM-encoded Ed25519 private key, null-terminated.
kidOptional key id written into the JWT header, or NULL.
exp_secondsSeconds until expiry (see cwist_jwt_sign()).
Returns
Heap-allocated null-terminated JWT string, or NULL on error. Caller must free with cwist_free().

Definition at line 629 of file jwt.c.

References cap, and JWT_ALG_ED25519.

◆ cwist_jwt_sign_es256()

char * cwist_jwt_sign_es256 ( const char *  payload_json,
const char *  pem_private_key,
const char *  kid,
long  exp_seconds 
)

Sign a JWT token with ES256 (ECDSA over P-256 with SHA-256).

Behaves like cwist_jwt_sign() except the signature is asymmetric: the header declares "alg":"ES256" and the signature is the 64-byte raw R||S form required by JOSE (RFC 7518 section 3.4).

Parameters
payload_jsonJSON string for the payload (see cwist_jwt_sign()).
pem_private_keyPEM-encoded EC private key (SEC 1 or PKCS#8), null-terminated. The key's curve must be P-256.
kidOptional key id written into the JWT header, or NULL.
exp_secondsSeconds until expiry (see cwist_jwt_sign()).
Returns
Heap-allocated null-terminated JWT string, or NULL on error. Caller must free with cwist_free().

Definition at line 624 of file jwt.c.

References cap, and JWT_ALG_ES256.

◆ cwist_jwt_split_chunks()

cwist_jwt_chunk_t * cwist_jwt_split_chunks ( const char *  token,
uint16_t  chunk_payload_size,
size_t *  out_count 
)

Split a JWT token into sequenced transport chunks.

Split a JWT token into sequenced chunks.

Parameters
tokenNull-terminated JWT string to split.
chunk_payload_sizeMaximum payload bytes per chunk; must be non-zero.
out_countSet to the number of chunks produced.
Returns
Heap-allocated array of out_count chunks, or NULL on invalid input, split failure, or allocation failure.

Each chunk's data buffer is owned by the caller and must be released with cwist_jwt_chunks_free().

Definition at line 800 of file jwt.c.

References cap, count, cwist_alloc_array(), cwist_seq_message_free(), cwist_seq_split(), cwist_jwt_chunk::data, and cwist_jwt_chunk::len.

Referenced by cwist_jwt_sign_chunks().

◆ cwist_jwt_verify()

cwist_jwt_claims * cwist_jwt_verify ( const char *  token,
const char *  secret 
)

Verify a JWT token and return the decoded claims.

Validates:

  • Structural integrity (three Base64URL-encoded parts).
  • HMAC-SHA256 signature.
  • "exp" claim (token must not be expired) if present.
Parameters
tokenNull-terminated JWT string ("header.payload.sig").
secretHMAC secret key (null-terminated).
Returns
Pointer to a cwist_jwt_claims object on success, NULL on failure. Caller must free with cwist_jwt_claims_destroy().

Definition at line 748 of file jwt.c.

References cap, and JWT_ALG_HS256.

Referenced by cwist_jwt_verify_chunks().

◆ cwist_jwt_verify_chunks()

cwist_jwt_claims * cwist_jwt_verify_chunks ( const cwist_jwt_chunk_t *  chunks,
size_t  count,
const char *  secret 
)

Reassemble sequenced chunks into a token, verify it, and return its claims.

Reassemble sequenced JWT chunks and verify the resulting token.

Parameters
chunksArray of sequenced chunks carrying the JWT token.
countNumber of entries in chunks.
secretShared HS256 signing secret.
Returns
Heap-allocated verified claims object, or NULL when assembly, parsing, signature verification, or claim validation fails.

The caller owns the result and must release it with cwist_jwt_claims_destroy().

Definition at line 921 of file jwt.c.

References cap, count, cwist_free(), cwist_jwt_join_chunks(), and cwist_jwt_verify().

◆ cwist_jwt_verify_ed25519()

cwist_jwt_claims * cwist_jwt_verify_ed25519 ( const char *  token,
const char *  pem_key 
)

Verify an Ed25519-signed JWT token and return the decoded claims.

The header must declare exactly "alg":"EdDSA". See cwist_jwt_verify_es256() for the verification contract.

Parameters
tokenNull-terminated JWT string ("header.payload.sig").
pem_keyPEM-encoded Ed25519 public key (or private key), null-terminated.
Returns
Pointer to a cwist_jwt_claims object on success, NULL on failure. Caller must free with cwist_jwt_claims_destroy().

Definition at line 756 of file jwt.c.

References cap, and JWT_ALG_ED25519.

◆ cwist_jwt_verify_es256()

cwist_jwt_claims * cwist_jwt_verify_es256 ( const char *  token,
const char *  pem_key 
)

Verify an ES256-signed JWT token and return the decoded claims.

The header must declare exactly "alg":"ES256" (a token signed with any other algorithm is rejected, which also closes the HS256/ES256 confusion class of RFC 8725 section 2.1) and the signature must verify against the public half of pem_key. The "exp"/"nbf" checks match cwist_jwt_verify().

Parameters
tokenNull-terminated JWT string ("header.payload.sig").
pem_keyPEM-encoded EC P-256 public key (or private key; the public half is used), null-terminated.
Returns
Pointer to a cwist_jwt_claims object on success, NULL on failure. Caller must free with cwist_jwt_claims_destroy().

Definition at line 752 of file jwt.c.

References cap, and JWT_ALG_ES256.