Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jwt Signature Algorithm Eddsa Laravel Package

web-token/jwt-signature-algorithm-eddsa

EdDSA (Ed25519) signature algorithm support for the web-token/jwt-framework. Adds Ed25519 signing and verification to PHP JWT applications, letting you issue and validate compact JWS tokens with modern elliptic-curve cryptography.

View on GitHub
Deep Wiki
Context7

Getting Started

What this package is. A single-purpose leaf of the web-token/jwt-* family. It ships one class — Eddsa (JWS alg: EdDSA, Ed25519 curve, RFC 8037) — that plugs into the framework's AlgorithmManager. There is no service provider, no config, no facade. In Laravel you wire it yourself.

Install.

composer require web-token/jwt-signature-algorithm-eddsa
# You almost certainly also need:
composer require web-token/jwt-signature web-token/jwt-core
# or just take the meta-package, which pulls this in transitively:
composer require web-token/jwt-library

Check composer show web-token/jwt-signature-algorithm-eddsa first — if you already depend on jwt-library or jwt-framework, it is probably already there.

Prerequisites. PHP 7.2+ with ext-sodium (php -m | grep sodium). Sodium is bundled with PHP 7.2+, so this is normally a no-op; only very old/stripped images need paragonie/sodium_compat.

Where to look first. vendor/web-token/jwt-signature-algorithm-eddsa/src/Eddsa.php — it is ~40 lines. Read it once and you understand the whole package: sign() reads d off the JWK and calls sodium_crypto_sign_detached, verify() reads x and calls sodium_crypto_sign_verify_detached.

First use case — sign and verify a detached JWS.

use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\Eddsa;

// Generate once, store privately (base64url, no padding — same variant JWK uses)
$kp = sodium_crypto_sign_keypair();
$priv = sodium_crypto_sign_secretkey($kp);
$pub  = sodium_crypto_sign_publickey($kp);

$b64 = fn (string $b) => sodium_bin2base64($b, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);

$privateJwk = new JWK(['kty' => 'OKP', 'crv' => 'Ed25519', 'd' => $b64($priv), 'x' => $b64($pub)]);
$publicJwk  = new JWK(['kty' => 'OKP', 'crv' => 'Ed25519', 'x' => $b64($pub)]);

$alg = new Eddsa();
$sig = $alg->sign('header.payload', $privateJwk);
$ok  = $alg->verify($publicJwk, 'header.payload', $sig); // true

If you are on a v2 install the namespace is WebToken\JWT\Signer\Algorithm\Eddsa and you construct it as a Signer with WebToken\JWT\Signer\Key\InMemory::base64Encoded(...). Grep the vendor directory before copying snippets from the internet.

Implementation Patterns

1. Bind the algorithm once in a service provider. The classes are stateless and cheap, but you want the AlgorithmManager to be the single source of truth so nothing constructs a mismatched set of algorithms.

// app/Providers/AppServiceProvider.php
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Signature\Algorithm\Eddsa;

$this->app->singleton(AlgorithmManager::class, fn () => new AlgorithmManager([
    new Eddsa(),
]));

2. Signing a JWT (v3 API, JWSBuilder).

use Jose\Component\Signature\JWSBuilder;

$jwsBuilder = new JWSBuilder(app(AlgorithmManager::class));

$jws = $jwsBuilder
    ->create()
    ->withPayload(json_encode($claims))
    ->addSignature($privateJwk, ['alg' => 'EdDSA', 'typ' => 'JWT', 'kid' => $kid])
    ->build();

$token = $jws->getSignature(0)->getSignature();   // detatched sig
// or serialize the full compact JWS via your serializer of choice

Do not sign the raw JSON — the compact form signs base64url(header).base64url(payload). Using the builder is what saves you from getting this wrong by hand.

3. Verifying. Verification should be keyed by kid against a public key set (JWKS), not by a single hard-coded key, if you ever rotate:

use Jose\Component\Signature\JWSVerifier;

$verifier = new JWSVerifier(app(AlgorithmManager::class));

$jwk = $this->keyStore->find($jws->getSignature(0)->getProtectedHeader()['kid']);
$valid = $verifier->verifyWithKey($jws, $jwk, 0);

4. Layering with claim checks. This package only proves the signature. Pair it with web-token/jwt-checker (exp/iat/nbf/aud/iss) and your own iss/aud assertions, or do them with Laravel's validator. Never trust a JWS you have only signature-verified.

5. Key storage in Laravel. Keep the private JWK in a secrets manager or env() holding the base64url d; keep the public set in config/jwt.php (or serve it from a /.well-known/jwks.json route). A JWKS route built from ['kty','crv','x','kid'] is the standard pattern for a Laravel API issuing tokens to other services.

6. Interop. Tokens are standard RFC 8037 JWTs — lcobucci/jwt v5 and firebase/php-jwt both read them natively. Use this package when you are already inside web-token (you have jwt-encryption, jwt-checker, or the framework's other components); if you are building a single-issuer API from scratch, firebase/php-jwt is lighter and does EdDSA out of the box.

7. Testing. Assert on RFC 8037 Appendix A test vectors, not on your own output. EdDSA is deterministic, so a golden-file test of a signed token is actually meaningful (unlike ECDSA), but pinning test tokens to your key still rots if the key changes.

Gotchas and Tips

  • Base64url, no padding. JWK values must use the URL-safe alphabet without =. A base64_encode()d key produces a valid-looking JWK whose signatures silently never verify. This is the #1 source of "it doesn't work" with this package.
  • d vs x are not interchangeable. sign() requires d (and will throw if missing); verify() requires x. A "full" keypair JWK with both works for both, but never ship d to a verifier.
  • alg is EdDSA, not Ed25519. The header value is the JWS algorithm name. The crv is Ed25519. Mixing them makes other libraries reject the token. Ed25519 as an algorithm name only appears in some non-standard tooling.
  • Ed448 is not supported. This package covers Ed25519 only. If you need Ed448 you are writing your own SignatureAlgorithm wrapper around sodium_crypto_sign_*448_*.
  • Deterministic signatures. Same payload + key ⇒ identical signature every time. Do not use the signature as a nonce, cache key, or replay token.
  • AlgorithmManager must include Eddsa. If you build a JWSVerifier with only HS256, verifyWithKey throws SignatureException ("algorithm not supported"), not a generic false. Catch Jose\Component\Signature\Exception\* and Jose\Component\Core\Exception\JWKException, and translate them to a 401 — never let the library exception's message reach the client, it often leaks header content.
  • No kid auto-population. If you rotate keys, you must set kid in addSignature() and implement lookup yourself; this package will happily verify against the wrong key and return false with no indication why.
  • Versioned namespaces. Jose\Component\... (v1, v3) vs WebToken\... (v2) — the web-token/* packages have flipped their namespace twice. The v2 "Signer/InMemory" API and the v3 "Algorithm/JWK" API are not compatible. Always check the installed major with composer show before copying examples.
  • Sodium compat fallback is slow. If ext-sodium is missing, some installs pull paragonie/sodium_compat; verification then becomes pure-PHP. Fine in dev, a latency problem in a token-heavy API. Fail fast: if (!extension_loaded('sodium')) throw ... at boot in production.
  • Extension points. The class extends Jose\Component\Signature\Algorithm\SignatureAlgorithm. Overriding sign()/verify() in a subclass is the supported way to add logging, metrics, or to enforce a minimum key length — there is no middleware/hook layer.
  • Stars are misleading here. 15 stars reflects that this is a leaf package almost nobody installs directly, not its quality. It is maintained as part of the web-token monorepo and is a stable, boring dependency — treat it as infrastructure, not a library you follow.
  • Debugging tip. EdDSA failures are almost always key encoding, not crypto. Dump both JWKs' x values and compare them; if they differ, your signer and verifier are not using the same keypair and the algorithm class is fine.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log