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

Sr25519 Bindings Laravel Package

gmajor/sr25519-bindings

PHP bindings for sr25519 cryptography, enabling Substrate/Polkadot-compatible key handling, signing, and signature verification in PHP and Laravel applications through a simple native-backed API.

View on GitHub
Deep Wiki
Context7

Getting Started

gmajor/sr25519-bindings is a thin PHP wrapper around a native Rust implementation of sr25519 — the Schnorrkel/Ristretto signature scheme used by Substrate-based chains (Polkadot, Kusama, and most parachains). You reach for it when your Laravel app needs to generate sr25519 keypairs, sign payloads, or verify signatures produced by a Substrate wallet or service. It is not a chain client; it does no RPC, no SS58 encoding, no mnemonic-to-address UI. It is the cryptography only.

Minimal setup:

composer require gmajor/sr25519-bindings
  1. Enable FFI. The package calls into a native shared library, so ext-ffi must be loaded and enabled. In php.ini: ffi.enable=true for local dev, ffi.enable=preload in production if you can preload. Confirm with php -r "var_dump(extension_loaded('ffi'));".
  2. Confirm the bundled native library matches your platform. Check vendor/gmajor/sr25519-bindings for the shipped .so/.dylib/.dll and that the architecture (x86_64 vs arm64, glibc vs musl) matches your runtime. This is the single most common reason the package "doesn't work."
  3. Smoke test in tinker before writing any application code:
use Sr25519\Sr25519;

$sr   = new Sr25519();
$pair = $sr->generateKeypair();                 // ['secretKey' => ..., 'publicKey' => ...]
$sig  = $sr->sign('hello', $pair['secretKey']);

var_dump($sr->verify($sig, 'hello', $pair['publicKey'])); // true

Treat the exact method names as something to verify against vendor/gmajor/sr25519-bindings/src — the repo is small (2 stars, 0 dependents, last release 2024-10-15) and the README is the only spec you get.

First real use case: "Sign in with Polkadot." A user connects a wallet, your app issues a nonce, the wallet signs it, you verify with this package, and you log them in. That one flow exercises key generation for tests, verification, encoding discipline, and error handling — everything you need to know about living with this package.

Implementation Patterns

Bind it once, hide it behind a contract. Never let new Sr25519() leak into controllers. Create app/Contracts/Sr25519Signer.php with generate(), sign(), verify(), publicKeyFromSecret(), and bind a concrete adapter in a service provider as a singleton. If the native library ever breaks on a PHP upgrade, you swap one class — or move to an HTTP sidecar — without touching business logic.

// app/Providers/Sr25519ServiceProvider.php
$this->app->singleton(Sr25519Signer::class, fn () => new NativeSr25519Signer(
    config('sr25519.library_path')
));

Wallet login (nonce challenge). Issue a random challenge, store it in the session or a login_challenges table with an expiry, and verify the returned signature against the public key the user claims. Bind the verified public key to the user record, then invalidate the challenge. Keep the signed message byte-identical to the one you issued — whitespace, newlines, and a 0x prefix mismatch are the top cause of "valid signature rejected."

Verify inbound payloads, don't trust the transport. If a Substrate-based service or relayer posts to a webhook, have it include publicKey, signature, and the raw body, and verify the signature over the raw request body before json_decode(). Re-encoding JSON and then verifying will fail.

Server-side signing for relayers and custodial flows. Generate keypairs server-side only when you must, store the secret with Laravel's encrypted cast or in a KMS, and pull it via a config value rather than a model attribute you might accidentally serialize. Sign in a queued job when throughput matters; each call is fast, but a loop over thousands of items will pin a worker.

Derivation for per-user addresses. sr25519 supports soft and hard junctions for deriving child keypairs from a parent. Use it to give each user a deterministic deposit address from one root seed. Write a test against a known vector (the well-known //Alice dev account is the standard) before trusting your junction syntax.

Testing. Fake the contract in feature tests so CI never needs FFI or the native library:

$this->mock(Sr25519Signer::class, fn ($m) => $m
    ->shouldReceive('verify')->andReturn(true));

Keep a small @requires extension ffi test suite with fixed keys and real signatures to catch native-library regressions on deploy. Run those against a staging image, not the dev laptop only.

Validation. Add a HexSignature rule (64 bytes / 128 hex chars) and a PublicKey rule (32 bytes / 64 hex chars) so malformed input is rejected by the validator rather than reaching FFI.

Gotchas and Tips

  • FFI is off by default almost everywhere. Docker php:8.x-fpm images, many managed hosts, and hardened production php.ini disable it. Add docker-php-ext-install ffi (or the equivalent) plus ffi.enable=1 to your image, and assert it at boot in a health check so you fail loudly instead of at first login.
  • glibc vs musl. Alpine images and the prebuilt .so often disagree. If you see a load failure on Alpine, either switch the base image to Debian-slim or build the Rust library yourself for the musl target.
  • Resolve paths absolutely. The native library path resolves relative to the process working directory, which differs between FPM, queue workers, and artisan. Use base_path() or __DIR__, and put the path in config/sr25519.php so you can override per environment.
  • Pick one encoding and enforce it. Public keys are 32 bytes, signatures 64, secrets 64. Choose hex (most Substrate tooling) or raw binary and convert at the boundary with bin2hex/hex2bin. Strip 0x prefixes in one place. Half the bugs in this space are 0x-prefix and case-sensitivity bugs.
  • This package does not encode SS58 addresses. Displaying 5Grwva… requires base58 + the Blake2b checksum, done separately. Don't expect getPublicKey() to return an address your users recognize.
  • Don't double-hash. sr25519 signs the message through its own Merlin transcript; wrap the exact bytes your counterparty signed. If you hash first because "that's what you do with ECDSA," verification will fail against every standard Substrate tool.
  • Error handling is thin. FFI-level failures and bad input lengths can surface as warnings or fatals rather than exceptions. Validate lengths and types before calling, and wrap calls in try/catch so a bad signature doesn't 500 the request.
  • Keep secrets out of logs. Laravel's exception handler will happily dump arguments in local debug. Never dd() a keypair, and scrub request payloads containing signatures or secrets in Handler::context().
  • Pin hard and vendor the binary. Two stars, zero dependents, and a single maintainer means no community safety net. Lock the exact version in composer.lock, commit the matching native library into your deploy artifact, and add a post-deploy smoke test that signs and verifies a fixed string.
  • Extension point: wrap, don't fork. The package is small enough to fork if you need a bug fix, but the maintenance cost of a native FFI fork is high. Prefer a Sr25519Signer interface with the package as one implementation and, if it ever becomes unmaintained, a Rust sidecar exposing /sign and /verify as the second. Your application code won't notice the difference.
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