paragonie/ecc
Pure-PHP elliptic curve cryptography (ECDSA/ECDH) with an OpenSSL 3+ fast path and hardened constant-time fallbacks. Fork of phpecc/mdanter. Supports secp256k1, NIST P-256/384/521, Brainpool, plus optional insecure curves.
Installation Add the package via Composer:
composer require paragonie/ecc:^2
Ensure ext-gmp is enabled in your PHP environment.
First Use Case: Key Generation
Generate a secure key pair using secp256k1 (Bitcoin curve):
use Mdanter\Ecc\EccFactory;
$curve = EccFactory::getSecgCurves()->curve256k1();
$keyPair = $curve->generator()->getKeyPair();
Where to Look First
EccFactory, SecureCurveFactory, and SchnorrSigner for modern workflows.SecureCurveFactory or OpenSSL-backed operations for production.Secure Key Generation:
Use SecureCurveFactory for default-secure curves (e.g., secp256k1, nistp256):
$secureFactory = EccFactory::getSecureSecgCurves();
$keyPair = $secureFactory->curve256k1()->generator()->getKeyPair();
Store private keys in encrypted storage (e.g., Laravel’s encryption facade).
Curve Selection:
Prefer nistp256/nistp384 for general use or secp256k1 for Bitcoin compatibility.
Avoid insecure curves (e.g., nistp192) unless explicitly allowed:
$insecureFactory = EccFactory::getNistCurves(null, true); // Bypass security check
$alicePrivateKey = ...; // From key pair
$bobPublicKey = ...; // From peer
$ecdh = new \Mdanter\Ecc\Crypto\EcDH();
$sharedSecret = $ecdh->calculateSharedSecret($alicePrivateKey, $bobPublicKey);
Use openssl_derive() or HKDF to derive symmetric keys from the shared secret.ECDSA Signing/Verification:
$signer = new \Mdanter\Ecc\Crypto\Signature\Signer();
$signature = $signer->signWithKey($privateKey, $message);
$valid = $signer->verifyWithKey($publicKey, $message, $signature);
Critical: Use HMAC-DRBG for k generation to avoid bias:
$rng = new \Mdanter\Ecc\Math\HmacDrbg();
$keyPair = $curve->generator($rng)->getKeyPair();
Schnorr Signatures (Modern Alternative):
$schnorr = new \Mdanter\Ecc\Crypto\Signature\SchnorrSigner();
$signature = $schnorr->signWithKey($privateKey, $message);
$valid = $schnorr->verifyWithKey($publicKey, $message, $signature);
Prefer Schnorr for new systems (forward secrecy, simpler verification).
AppServiceProvider:
public function register()
{
$this->app->singleton('ecc.secureFactory', function () {
return EccFactory::getSecureSecgCurves();
});
}
serialize() or json_encode() and encrypt with Laravel’s Crypt:
$encrypted = Crypt::encrypt($privateKey->getSecretScalar()->toString());
Insecure Curves:
nistp192).SecureCurveFactory or explicitly allow insecure curves with true flag.Side-Channel Attacks:
$curve = EccFactory::getNistCurves()->optimizedCurve256();
Key Reuse:
k in ECDSA breaks security.k generation (default in Signer).OpenSSL Dependency:
$curve->disableOpenssl();
Invalid Signatures:
hash_hmac with SHA-256/384/512).Performance:
nistp256) have minimal overhead vs. generic ECC.Custom Curves:
Extend CurveFactory to add non-standard curves (e.g., Curve25519):
class CustomCurveFactory extends CurveFactory {
public function curve25519() { ... }
}
Key Storage:
Implement KeyInterface for custom key formats (e.g., PEM):
class PemKey implements KeyInterface { ... }
Schnorr Hardening:
Override SchnorrSigner to enforce stricter k generation:
class StrictSchnorrSigner extends SchnorrSigner {
protected function generateK() { ... }
}
Caching Keys: Cache key pairs in Redis with a short TTL (e.g., 1 hour) to avoid regeneration:
$key = Cache::remember('ecc-key-pair', 3600, function () {
return $secureFactory->curve256k1()->generator()->getKeyPair();
});
Queue Jobs: Offload ECDH/Signature operations to queues to avoid blocking requests:
Dispatch(new HandleEcdh($alicePrivateKey, $bobPublicKey))->onQueue('ecc');
How can I help you explore Laravel packages today?