Signature algorithms¶
This framework comes with several signature algorithms. These algorithms are in the following namespace: Jose\Component\Signature\Algorithm.
| Algorithm | Description |
|---|---|
| HS256 HS384 HS512 |
HMAC with SHA-2 Functions |
| ES256 ES384 ES512 |
Elliptic Curve Digital Signature Algorithm (ECDSA) |
| ES256K | ECDSA over the secp256k1 curve with SHA-256 (RFC 8812). Since 4.3, see below |
| RS256 RS384 RS512 |
RSASSA-PKCS1 v1_5 |
| PS256 PS384 PS512 |
RSASSA-PSS |
| Ed25519 Ed448 |
Edwards-curve Digital Signature Algorithm (EdDSA), fully-specified per RFC 9864. Since 4.3; Ed448 needs PHP 8.4 |
| ML-DSA-44 ML-DSA-65 ML-DSA-87 |
Module-Lattice-Based Digital Signature Algorithm (ML-DSA, FIPS 204), post-quantum, per RFC 9964. Since 4.3; needs PHP 8.4 and OpenSSL 3.5 |
| EdDSA (only with the Ed25519 curve) | Deprecated by RFC 9864, use Ed25519. See below |
| none | Not a secure algorithm. Please use with caution |
The ES256K algorithm¶
ES256K — ECDSA over the secp256k1 curve with SHA-256, RFC 8812 — is a standard algorithm that lived in the experimental package for historical reasons. Since 4.3 it is Jose\Component\Signature\Algorithm\ES256K, next to ES256, and the Symfony Bundle registers it under the ES256K alias like any other algorithm. Keys are EC keys with crv: secp256k1; an ES256KKeyAnalyzer checks them.
Warning
Jose\Experimental\Signature\ES256K still works — it is a deprecated subclass of the new class, and the bundle keeps its service for the applications that inject it — but it is removed in 5.0. Change the use statement.
Known limitation, unchanged: a secp256k1 key exported to PEM cannot be loaded back through the key loader on some OpenSSL builds. Keep such keys as JWK.
The Ed25519 and Ed448 algorithms¶
RFC 9864 registers the fully-specified Ed25519 and Ed448 algorithms and deprecates the polymorphic EdDSA: the name of the algorithm alone must say which curve is in use. The keys are unchanged — an OKP key with crv: Ed25519 or crv: Ed448 — only the alg value differs.
<?php
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Signature\Algorithm\Ed25519;
use Jose\Component\Signature\Algorithm\Ed448;
$algorithmManager = new AlgorithmManager([new Ed25519(), new Ed448()]);
Each algorithm accepts its own curve only: Ed25519 refuses a key on Ed448 and Ed448 a key on Ed25519, with an InvalidKeyException.
Ed25519runs on thesodiumextension when it is loaded, asEdDSAalways did, and on OpenSSL otherwise (PHP 8.4 or later).Ed448runs on OpenSSL only, and needs PHP 8.4 or later — before that version PHP cannot ask OpenSSL for the digest-less signature the Edwards curves require.Ed448::isSupported()tells whether the platform can run it; the constructor throws aMissingDependencyExceptionwhen it cannot, and the Symfony Bundle registers the algorithm only when it can run.
Warning
EdDSA is deprecated since 4.3. It keeps working — the tokens already in circulation still verify — and signing with it raises a deprecation notice. Migrate the issuer first, then the verifiers:
- register
Ed25519next toEdDSAon the verifiers, so that bothalgvalues are accepted; - switch the issuer to
Ed25519: same key,alg: Ed25519in the header; - once no
EdDSAtoken is in circulation any more, dropEdDSAfrom the verifiers.
A key carrying alg: EdDSA is refused by the Ed25519 algorithm, and a key carrying alg: Ed25519 by EdDSA: update the alg of the keys with the issuer, or leave it out during the migration. The key analyzer reports keys still declaring alg: EdDSA.
The ML-DSA-44, ML-DSA-65 and ML-DSA-87 algorithms¶
RFC 9964 registers ML-DSA (FIPS 204, the module-lattice signature scheme) for JOSE: the first post-quantum signature of the registries. The three parameter sets are the pure ML-DSA of FIPS 204 with an empty context — no HashML-DSA, which section 7.2 of the RFC excludes.
The keys are of the AKP type (section 3), with pub the encoded public key and priv the 32-byte seed — the only private key representation the RFC allows (section 4), from which the whole key is derived. alg is required on every AKP key: the type says nothing about the algorithm.
<?php
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\Algorithm\MLDSA44;
use Jose\Component\Signature\Algorithm\MLDSA65;
use Jose\Component\Signature\Algorithm\MLDSA87;
$algorithmManager = new AlgorithmManager([new MLDSA44(), new MLDSA65(), new MLDSA87()]);
$key = (new JWKFactory())->mldsa('ML-DSA-65', ['use' => 'sig']);
// {"kty":"AKP","alg":"ML-DSA-65","pub":"...","priv":"...32-byte seed...","use":"sig"}
Before OpenSSL sees a key, the algorithm checks it as section 7.3 requires: alg present and equal to the algorithm, pub of the size of the parameter set (1312, 1952 or 2592 bytes), priv of exactly 32 bytes, and — when the key carries both — that pub is the key the seed expands to. Signatures are 2420, 3309 or 4627 bytes; a signature of another length is false before any computation.
Warning
Platform requirement. The computation is OpenSSL's, and needs PHP 8.4 (the first version able to sign without a digest through OpenSSL) and an OpenSSL 3.5 runtime. The OpenSSL check is a runtime probe — OPENSSL_VERSION_TEXT reports the headers PHP was built against, not the library it loaded — so MLDSA44::isSupported() tells whether the platform can run the algorithms; the constructors throw a MissingDependencyException naming the missing piece, and the Symfony Bundle registers the algorithms only when they can run.
The none algorithm¶
Since 4.3, none lives in its own package, so that enabling it is an explicit and auditable decision:
It is deliberately not part of web-token/jwt-experimental: none is perfectly standard, and an application asking for Blake2b should not get it in the bargain.
Warning
Jose\Component\Signature\Algorithm\None still works — it is an empty subclass of the new class — but it is deprecated since 4.3 and removed in 5.0. In the Symfony Bundle, the configuration alias is unchanged: none still names the algorithm.
Danger
none disables signature verification altogether. Read Security Recommendations before enabling it.
Experimental algorithms¶
The following signature algorithms are experimental and must not be used in production unless you know what you are doing. They are proposed for testing purpose only.
They are provided through the package web-token/jwt-experimental.
| Algorithm | Description |
|---|---|
| RS1 | RSASSA-PKCS1 v1_5 with SHA-1 hashing function |
| HS1 | HMAC with SHA-1 hashing function |
| HS256/64 | HMAC with SHA-256 truncated to 64 bits |
| BP256R1 | ECDSA using the brainpoolP256r1 curve (BP-256) and SHA-256 |
| BP384R1 | ECDSA using the brainpoolP384r1 curve (BP-384) and SHA-384 |
| BP512R1 | ECDSA using the brainpoolP512r1 curve (BP-512) and SHA-512 |
| Blake2b | Blake2b MAC algorithm. Sodium extension required |
Warning
The Brainpool algorithms and their curves are not registered with IANA. The identifiers BP256R1/BP384R1/BP512R1 and BP-256/BP-384/BP-512 follow the convention already adopted by the other implementations, so tokens using them are only interoperable with the implementations sharing that convention.
The curves themselves are part of the core library: creating a Brainpool key or using one with ECDH-ES/ECDH-SS does not require the experimental package.
How to use¶
These algorithms have to be used with the Algorithm Manager. They do not need any arguments.
Example: