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
- Inspect the SodiumException message (available via $e->getPrevious()) to see the exact libsodium complaint and fix the key material accordingly.
- 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.
- 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.
- 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
- Store and pass keys as raw binary; decode base64/hex exactly once at load time.
- Use sodium_crypto_sign_secretkey() output directly rather than hand-assembled key material.
- Keep signing and verification keys from the same keypair and label them clearly (secret vs public).
- Unit-test sign() against a known RFC 8032 vector at boot to catch key-format regressions.
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)