Skip to content

v2.1.0 - secp256k1 support

Choose a tag to compare

@AdmWalker AdmWalker released this 18 Sep 18:02
· 27 commits to master since this release
8292d4f

Adds secp256k1 alongside ML-DSA-65, using ext-openssl — no new Composer package, and no ext-gmp.

Use it unless the identity must outlive a cryptographically relevant quantum computer: roughly 22× smaller per transaction, works with hardware wallets and HSMs, and it's the only way to sign for an identity created before post-quantum support.

It also closes the gap this SDK had alone. ML-DSA private keys are not portable here, because the underlying library only does seeds. secp256k1 private keys are — so a PHP caller can share one identity with every other Activeledger SDK.

PHP's OpenSSL is the same implementation the ledger verifies with, so interop is structural rather than hopeful.

Measured against the published vectors

  • openssl_verify accepts all 7 high-S signatures — what's needed, since the ledger produces high-S freely and a verifier enforcing low-S would reject roughly half of everything it makes.
  • Public keys build from raw SEC1 bytes in both forms, and private keys from a bare 32-byte scalar.

Signing folds S low, because OpenSSL doesn't normalise and @noble/curves rejects high-S by default.

⚠️ One difference from the other SDKs

Signing is not RFC 6979 deterministic — OpenSSL uses a random k with no way to inject one, so this SDK cannot reproduce the published reference bytes.

That costs a test, not correctness: everything it emits is a valid, canonical, low-S signature, and the suite verifies the published deterministic signatures even though it cannot reproduce them.

Encoding

  • Keys are 0x-prefixed hex, not base64 — the prefix is required.
  • Two valid public key lengths: 33 compressed (default), 65 uncompressed.
  • Private scalars are always 32 bytes.

bitcoin and ethereum parse as secp256k1 and are never emitted.

⚠️ Breaking

Signer::publicKeyBase64 → Signer::publicKey.

Testing

97 unit tests across PHP 8.1–8.5, plus 10 live tests against a real 4-node network onboarding both public key forms.