lcobucci/jwt · error · Lcobucci\JWT\Signer\InvalidKeyProvided

<SodiumException message>

Error message

<SodiumException message>

What it means

This library wraps sodium_crypto_sign_detached (Ed25519 detached signing). If libsodium rejects the call it throws SodiumException, which Eddsa::sign catches and rethrows as InvalidKeyProvided with the original message and exception chained as previous. In practice it means the Key contents are not a valid Ed25519 secret key (wrong length/format) or the payload/key pair is unusable for signing.

Solutions

  1. Inspect the SodiumException message (available via $e->getPrevious()) to see the exact libsodium complaint and fix the key material accordingly.
  2. Ensure the key is a raw 64-byte Ed25519 secret key: if stored base64/hex-encoded, decode it (base64_decode / hex2bin) before constructing the Key.
  3. Regenerate a valid key pair with sodium_crypto_sign_keypair() and use sodium_crypto_sign_secretkey() for signing and sodium_crypto_sign_publickey() for verification.
  4. Verify you are not swapping secret and public keys between sign() and verify().

Example fix

// before
$key = new Key(base64_encode($secretKey));
$signature = $signer->sign($payload, $key); // InvalidKeyProvided
// after
$key = new Key(base64_decode($secretKey));
$signature = $signer->sign($payload, $key);
Defensive patterns

Strategy: try-catch

Validate before calling

if (strlen($key->contents()) !== SODIUM_CRYPTO_SIGN_SECRETKEYBYTES) {
    throw new \InvalidArgumentException('Ed25519 secret key must be ' . SODIUM_CRYPTO_SIGN_SECRETKEYBYTES . ' raw bytes');
}

Type guard

function isValidEd25519SecretKey(string $key): bool
{
    return strlen($key) === SODIUM_CRYPTO_SIGN_SECRETKEYBYTES;
}

Try / catch

try {
    $signature = $signer->sign($payload, $key);
} catch (Lcobucci\JWT\Signer\InvalidKeyProvided $e) {
    $root = $e->getPrevious(); // SodiumException with the libsodium detail
    // log $root->getMessage() and fail the operation
}

Prevention

When it happens

Trigger: Calling Eddsa::sign($payload, $key) where $key->contents() is not exactly SODIUM_CRYPTO_SIGN_SECRETKEYBYTES (64) bytes of a valid Ed25519 secret key, or is an empty/garbage string; sodium also throws when the underlying key material cannot be used by sodium_crypto_sign_detached.

Common situations: Passing a base64/hex-encoded key without decoding it first; passing a public key or an Ed25519 seed alone instead of the full secret key; truncating or corrupting key files; mixing up signing and verification keys; using keys generated by another algorithm (e.g. HMAC or RSA keys).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14). Data as JSON: /api/errors/6e38ca625f2f4c1a. Report an issue: GitHub.

Appendix: source

Thrown at src/Signer/Eddsa.php:24

use Lcobucci\JWT\Signer;
use SodiumException;

use function sodium_crypto_sign_detached;
use function sodium_crypto_sign_verify_detached;

final readonly class Eddsa implements Signer
{
    public function algorithmId(): string
    {
        return 'EdDSA';
    }

    public function sign(string $payload, Key $key): string
    {
        try {
            return sodium_crypto_sign_detached($payload, $key->contents());
        } catch (SodiumException $sodiumException) {
            throw new InvalidKeyProvided($sodiumException->getMessage(), 0, $sodiumException);
        }
    }

    public function verify(string $expected, string $payload, Key $key): bool
    {
        try {
            return sodium_crypto_sign_verify_detached($expected, $payload, $key->contents());
        } catch (SodiumException $sodiumException) {
            throw new InvalidKeyProvided($sodiumException->getMessage(), 0, $sodiumException);
        }
    }
}

View on GitHub (pinned to 375813049c)