Pure-PHP secp256k1 elliptic-curve arithmetic and RFC 6979 deterministic ECDSA — sign, verify and recover for Ethereum and Bitcoin signatures.
amashukov/secp256k1-php implements the secp256k1 elliptic curve and ECDSA signature primitives in pure PHP on top of ext-gmp. It covers point arithmetic, RFC 6979 deterministic signing, signature verification and public-key recovery — the building blocks behind Ethereum and Bitcoin signatures, EIP-191 / EIP-712 signer derivation and EVM wallet tooling. Two static classes:
Secp256k1 — curve constants (P, N, Gx, Gy) and point arithmetic (pointAdd, pointDouble, scalarMul, scalarMulG).Ecdsa — RFC 6979 deterministic sign, verify, and recover (the latter is what EIP-191 / EIP-712 implementations call to derive a public key from a signature triple).The package is a leaf primitive — it ships with zero composer dependencies (ext-gmp + ext-hash from PHP core), and the EIP-191 / EIP-712 message-prefix hashing belongs in a downstream package that owns the keccak / domain-separator step.
pointAdd, pointDouble, scalarMul, scalarMulG over GMP big integers.04 || x || y uncompressed key from a (v, r, s) triple, the EIP-191 / EIP-712 signer step.ext-gmp + ext-hash only.@PER-CS formatted, CI-tested.simplito/elliptic-php is a fine general-purpose elliptic-curve library, but it is curve-agnostic and carries the machinery for many curves. amashukov/secp256k1-php is single-curve by design: it focuses exclusively on secp256k1 and the ECDSA operations EVM and Bitcoin tooling actually need — deterministic RFC 6979 signing, canonical low-S output and (v, r, s) recovery — with a smaller, audited surface and zero composer dependencies.
composer require amashukov/secp256k1-php
use Amashukov\Secp256k1\Secp256k1;
$p = Secp256k1::p(); // curve modulus
$n = Secp256k1::n(); // curve order
$G = Secp256k1::g(); // generator point ['x' => GMP, 'y' => GMP]
// Public key from a 32-byte private key.
$priv = hex2bin('c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4');
$d = gmp_import($priv);
$pub = Secp256k1::scalarMul($G, $d, $p); // ['x' => GMP, 'y' => GMP]
use Amashukov\Secp256k1\Ecdsa;
$msgHash = hex2bin('5e89218a87e0bd6df9fdc62af4a8a87f48c44fcab6cdeefd6c6d3fcdcad1b48d'); // 32 bytes
$privKey = hex2bin('c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4'); // 32 bytes
$signature = Ecdsa::sign($msgHash, $privKey);
// → ['r' => 32 bytes, 's' => 32 bytes, 'v' => 0|1]
Signatures are deterministic per RFC 6979 (same input → same output) and returned in canonical low-S form, so two clients signing the same payload produce byte-identical signatures.
$pubKey = "\x04" . str_pad(gmp_export($pub['x']), 32, "\x00", STR_PAD_LEFT)
. str_pad(gmp_export($pub['y']), 32, "\x00", STR_PAD_LEFT);
$ok = Ecdsa::verify($msgHash, $pubKey, $signature['r'], $signature['s']);
// Given a (v, r, s) signature triple from an EVM wallet:
$pubKey = Ecdsa::recover($msgHash, $signature['v'], $signature['r'], $signature['s']);
// → 65 raw bytes uncompressed (`04 || x || y`), or null on failure
The recovered public key can then be hashed (keccak-256 of x || y → take last 20 bytes) to derive the signer's Ethereum address.
ext-gmpext-hash (bundled with PHP core; used for HMAC-SHA256 in RFC 6979 nonce derivation)No composer dependencies.
Secp256k1::scalarMul walks the scalar bit-by-bit with conditional adds — it leaks timing information about secret scalars. Use this package for signing only when the resulting timing channel is acceptable for the deployment (server-side signing of own keys is generally fine; never use it to handle attacker-controlled scalars on shared hardware).Ecdsa::recover and Ecdsa::sign reject malformed lengths and out-of-range scalars at the public surface.Part of a modular pure-PHP blockchain toolkit:
| Package | Purpose |
|---|---|
| amashukov/keccak-php | Keccak-256 / SHA-3 / SHAKE hashing |
| amashukov/secp256k1-php | secp256k1 ECDSA sign / verify / recover |
| amashukov/rlp-php | Ethereum RLP encode / decode |
| amashukov/ton-cell-php | TON TLB Cell / Builder / Slice / BOC |
| amashukov/eip1559-tx-signer-php | EIP-1559 transaction signer |
| amashukov/abi-encoder-php | Ethereum ABI encoder |
| amashukov/eth-rpc-client-php | Ethereum JSON-RPC client |
| amashukov/eth-php | EVM umbrella package |
@PER-CS ruleset.MIT License.
How can I help you explore Laravel packages today?