Skip to content

Repository files navigation

Build Archs CodeQL

cjose

Implementation of JOSE for C/C++

Supported Algorithms

JWS signing algorithms (alg):

Identifier Algorithm Requires
HS256, HS384, HS512 HMAC with SHA-2
RS256, RS384, RS512 RSASSA-PKCS1-v1_5 with SHA-2
PS256, PS384, PS512 RSASSA-PSS with SHA-2
ES256, ES384, ES512 ECDSA with P-256, P-384 and P-521
ES256K ECDSA with secp256k1 OpenSSL built with secp256k1
Ed25519, Ed448 EdDSA (RFC 9864)
ML-DSA-44, ML-DSA-65, ML-DSA-87 ML-DSA (RFC 9964, US NIST FIPS 204) build option CJOSE_ENABLE_ML_DSA, OpenSSL >= 3.5

The polymorphic EdDSA identifier of RFC 8037, deprecated by RFC 9864, and none are not accepted.

The ML-DSA algorithms sign with the AKP key type of RFC 9964. They are pure ML-DSA over the JWS signing input, with the empty context string RFC 9964 requires; HashML-DSA is not part of that specification and is not offered.

JWE key management algorithms (alg):

Identifier Algorithm Requires
RSA-OAEP RSAES OAEP with SHA-1 and MGF1 with SHA-1
RSA-OAEP-256 RSAES OAEP with SHA-256 and MGF1 with SHA-256
RSA1_5 RSAES-PKCS1-v1_5 build option CJOSE_ENABLE_RSA1_5
A128KW, A192KW, A256KW AES Key Wrap
A128GCMKW, A192GCMKW, A256GCMKW AES GCM key wrapping
PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW PBKDF2 with HMAC SHA-2 and AES Key Wrap
dir direct use of a shared symmetric key
ECDH-ES ECDH-ES direct key agreement, with an EC key or an OKP X25519 or X448 key
ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW ECDH-ES with AES Key Wrap, with an EC key or an OKP X25519 or X448 key

The PBES2 salt input (p2s) is generated for every encryption, as RFC 7518 section 4.8.1.1 requires, and a caller-supplied one is refused. The iteration count (p2c) can be set in the header, per recipient where a JWE has several, and defaults to 8192. Beyond the 8 octet salt input the RFC requires, cjose applies limits of its own: it writes no fewer than 1000 iterations, the RFC's recommendation, it neither writes nor accepts more than 1000000, and it accepts no salt input longer than 1024 octets. What it accepts when decrypting is otherwise what RFC 7518 section 4.8.1.2 allows, any positive count, so that a conformant producer's JWE is readable whatever count it chose; the ceiling is what bounds the key derivation an unauthenticated JWE can demand, per recipient. These are policy rather than RFC validation, and each is a build option (see Build Options).

JWE content encryption algorithms (enc):

Identifier Algorithm
A128GCM, A192GCM, A256GCM AES GCM
A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 AES CBC with HMAC SHA-2

JWK key types (kty):

Identifier Keys Requires
RSA RSA
EC P-256, P-384, P-521, secp256k1 secp256k1: OpenSSL built with it
oct symmetric
OKP Ed25519, Ed448, X25519, X448
AKP ML-DSA-44, ML-DSA-65, ML-DSA-87 (RFC 9964) build option CJOSE_ENABLE_ML_DSA, OpenSSL >= 3.5

JWEs can be produced and consumed in both the compact and the JSON serialization, with one or more recipients.

Prerequisites

MAC OS X All of the prerequisites can be installed via brew.

Build Tools

  • CMake (>= 3.22)
  • A C17 compiler (LLVM/Clang >= 6.0, GCC >= 8.1 or MSVC >= 19.28)
  • Check (>= 0.12.0) - unit testing (e.g. check-devel)
  • Doxygen (>= 1.8) - API documentation (optional)
  • clang-format - source formatting (optional)

Libraries

  • OpenSSL >= 3.0.0 (>= 3.5 for the ML-DSA signature algorithms, see the CJOSE_ENABLE_ML_DSA build option below)
  • Jansson >= 2.3

Getting Started

cjose builds with CMake (>= 3.22):

git clone https://github.com/cisco/cjose.git
cd cjose
cmake -S . -B build
cmake --build build

By default both the shared and static libraries are built (and, when cjose is the top-level project, the unit tests).

Build Options

Pass options with -D<OPTION>=<VALUE> at configure time:

Option Default Description
CJOSE_BUILD_SHARED ON Build the shared/dynamic library
CJOSE_BUILD_STATIC ON Build the static library
CJOSE_BUILD_TESTS ON when top-level Build the unit tests (requires Check)
CJOSE_ENABLE_RSA1_5 OFF Enable the RSA1_5 (RSAES-PKCS1-v1_5) key encryption algorithm
CJOSE_ENABLE_ML_DSA OFF Enable the ML-DSA signature algorithms and the AKP key type (RFC 9964); requires OpenSSL >= 3.5
CJOSE_MSVC_STATIC_RUNTIME OFF (MSVC) Link against the static C runtime (/MT)
CJOSE_MACOS_DYLIB OFF (macOS) Build a plain .dylib instead of a framework
CJOSE_JWE_PBES2_MIN_ITERATIONS 1000 Lowest PBES2 iteration count cjose will produce
CJOSE_JWE_PBES2_MIN_ACCEPTED_ITERATIONS 1 Lowest PBES2 iteration count cjose will accept when decrypting
CJOSE_JWE_PBES2_MAX_ITERATIONS 1000000 Highest PBES2 iteration count cjose will produce or accept; keep at or above 100000, the highest default a mainstream producer ships
CJOSE_JWE_PBES2_DEFAULT_ITERATIONS 8192 PBES2 iteration count used when the caller sets no p2c
CJOSE_JWE_PBES2_MAX_SALT_LEN 1024 Largest PBES2 salt input cjose will accept, in octets

The PBES2 iteration counts must keep the order MIN_ACCEPTED_ITERATIONSMIN_ITERATIONSDEFAULT_ITERATIONSMAX_ITERATIONS, so setting one may mean setting another; a combination that does not is refused when the library is compiled.

For example, to build only the static library in debug mode:

cmake -S . -B build -DCJOSE_BUILD_SHARED=OFF -DCMAKE_BUILD_TYPE=Debug
cmake --build build

Dependencies in Non-Standard Locations

OpenSSL and Jansson are located automatically. If they live in a custom prefix, point CMake at it:

cmake -S . -B build -DCMAKE_PREFIX_PATH="/usr/local/opt/openssl;/usr/local/opt/jansson"

Tests

To run the unit tests:

ctest --test-dir build --output-on-failure -V

API Docs

To generate the Doxygen API documentation (requires Doxygen):

cmake --build build --target doxygen

The generated HTML is placed in build/doc/html.

Installing

cmake --install build --prefix /your/install/prefix

This installs the libraries, the public headers, a cjose.pc pkg-config file and a CMake package config.

Using cjose From Another Project

After installing, consume cjose from a CMake project via find_package:

find_package(cjose REQUIRED)
target_link_libraries(myapp PRIVATE cjose::cjose)

The cjose::cjose target aliases the shared/dynamic library when it is built, or the static library when CJOSE_BUILD_SHARED=OFF. The explicit cjose::cjose_shared target is also available when that library type is built. Using the shared library does not require the OpenSSL or Jansson development packages on the consuming system.

Static consumers need cjose's private dependencies and can request them and the explicit static target with:

find_package(cjose REQUIRED COMPONENTS static)
target_link_libraries(myapp PRIVATE cjose::cjose_static)

Alternatively, embed the sources directly with add_subdirectory() or FetchContent; the same CMake targets are provided.

Contributing

Before Submitting PR

  • Run cmake --build build --target clang-format
  • Run ctest --test-dir build --output-on-failure -V

About

C library implementing the Javascript Object Signing and Encryption (JOSE)

Resources

Contributing

Stars

122 stars

Watchers

13 watching

Forks

Releases

Packages

Used by

Contributors

Languages