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 Framework Schnorr Laravel Package

public-square/jwt-framework-schnorr

Adds Schnorr signature support to JWT workflows in PHP and Laravel, letting you issue and verify compact, tamper-evident tokens using modern public-key cryptography. A focused integration for developers needing Schnorr-based JWT signing.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a cryptography package (Schnorr signatures, with an experimental SS256K curve) at v0.1.0. Treat it as pre-stable: the API surface is still moving, so read README.md, src/, and tests/ before writing application code against it.

Install and pin. Because this is a 0.x release, SemVer allows breaking changes in minor bumps. Pin it:

composer require <vendor>/<package>:0.1.0

Check the Composer constraints in composer.json first — crypto packages commonly require ext-gmp or ext-bcmath and a minimum PHP version. Confirm these on your CI image and in config/platform.php before deploying.

Where to look first, in order:

  1. README.md — quickstart for key generation, sign, verify.
  2. tests/ — the new testing suite is the best documentation of intended usage; the fixtures likely include known-answer test vectors.
  3. src/ — the public interfaces (signer, key pair, signature value objects). These, not the concrete classes, are what you should type-hint.

First use case. A single end-to-end round trip, written as a test rather than a tinker session:

$keyPair = $signer->generateKeyPair();          // or fromSecretKey(config(...))
$signature = $signer->sign($message, $keyPair->privateKey());

$signer->verify($message, $signature, $keyPair->publicKey()); // true

Get that green before wiring anything into a controller. If it fails, the problem is almost always encoding (hex vs. raw binary) or a missing PHP extension — not your application code.

Implementation Patterns

Wrap the package behind your own interface. This is the single most valuable thing you can do at v0.1.0. Bind the package to a narrow app-owned contract so a breaking change in 0.2.0 is a one-file edit:

interface PayloadSigner {
    public function sign(string $payload): string;          // returns hex
    public function verify(string $payload, string $sig, string $pubKey): bool;
}

$this->app->singleton(PayloadSigner::class, fn () => new SchnorrPayloadSigner(
    secretKey: config('signing.secret_key'),
));

Everything else in the app — middleware, jobs, form requests — depends on PayloadSigner, never on the package namespace.

Verification as middleware or a form request. For signed webhooks or API requests, verify the detached signature in one place and reject early:

public function handle($request, Closure $next)
{
    $ok = $this->signer->verify(
        $request->getContent(),                       // raw body, not parsed
        $request->header('X-Signature'),
        $request->header('X-Public-Key'),
    );

    abort_unless($ok, 401);
    return $next($request);
}

The raw body matters — $request->all() re-serialises and the bytes will not match.

Keys come from config or a vault, never from code. Put the secret key in .env as hex, read it through a config key, and keep that config file out of anything you log or cache. For anything beyond an internal service, load from a KMS/secret manager at boot and cache the resolved key pair as a singleton so you parse it once per request lifecycle.

Test against vectors, not against yourself. Sign-then-verify proves nothing about correctness — a broken implementation round-trips fine. Use the published test vectors the new testing suite ships with, and add a cross-implementation check (sign in PHP, verify in libsodium/another language) in CI if the signatures cross a trust boundary.

Fake it in feature tests. Bind a deterministic fake PayloadSigner for HTTP tests so you are testing your middleware and routing, not the cryptography. Keep a separate, small integration suite that runs the real signer.

Gotchas and Tips

  • v0.1.0 is a warning, not a version number. Expect a renamed method or changed signature at any minor bump. Pin exactly, upgrade deliberately, and read the diff.
  • SS256K is flagged experimental for a reason. Do not use it for anything with value attached. The mature path is the default curve; keep the experimental one behind a config flag you never flip in production, so it cannot be reached by accident.
  • Nonce reuse is catastrophic. If the package exposes a nonce or randomness parameter, do not supply your own. If signatures come out identical for different messages under the same key, stop and investigate — that is the failure mode that leaks the private key. Prefer the deterministic/RFC-6979-style path if offered.
  • Encoding is the number-one source of "invalid signature" bugs. Establish a convention (hex strings at the boundary, raw bytes internally) and enforce it with typed value objects. A signature that verifies in tests and fails in production is nearly always a base64/hex/bin2hex mismatch, or a body that picked up whitespace or a trailing newline in transit.
  • Watch php artisan config:cache. Reading .env directly inside the package or your wrapper works in local and silently breaks in a cached-config deploy. Always go through config().
  • Redact secrets in logs and error traces. Crypto exceptions frequently include key material or partial signatures in the message. Register a report() hook or a redaction processor before you ship.
  • Check for timing-safety notes. === on secrets and signature comparisons should be hash_equals. If the package's verify does not document constant-time comparison, wrap or patch it.
  • Debug by narrowing, not by dumping. Binary and hex values are unreadable in dd(). Assert on bin2hex(), lengths (32-byte key, 64-byte Schnorr signature), and vector equality.
  • Extension points to look for: a curve/algorithm enum or config switch, a Signature/KeyPair value object you can extend, and a service-provider binding you can override in AppServiceProvider. Favour configuring these over forking.
  • Composer updates landed in this release. Run composer update --with-dependencies in a branch, and check that no transitive dependency pulled in a conflicting ext- requirement before merging.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource