web-auth/cose-lib
CBOR Object Signing and Encryption (COSE) library for PHP with full support for COSE_Sign1, Sign, Encrypt0, Encrypt, Mac0 and Mac tags, plus ECDSA, EdDSA, RSA, HMAC algorithms. PHP 8.1+ and WebAuthn/FIDO2 compatible.
Architecture fit. web-auth/cose-lib is a stateless, synchronous, in-process codec and crypto-primitive library — no I/O, no persistence, no framework coupling, no service provider. It sits naturally in the infrastructure layer behind an application-owned port (CoseVerifier, CoseSigner interfaces), which keeps COSE types out of controllers, jobs, and domain models. For a Laravel codebase this is a clean, low-ceremony dependency; the architectural cost is in the policy layer you must build around it, not in the library itself.
Integration feasibility. Composer-only install, PHP 8.1+, strict types, PHPStan-clean, PSR-4 namespaces, MIT license. Actual integration effort is small (hours), but the dependency tree is not: spomky-labs/cbor-php (required for tag support), spomky-labs/pki-framework, brick/math, ext-openssl, ext-json. Those overlap with web-auth/webauthn-lib, so if the real requirement is WebAuthn/FIDO2, this package should arrive transitively rather than be adopted directly.
Technical risk. This is security-critical, low-level code, and the README makes the division of responsibility explicit: the library parses COSE structures and implements algorithms, but the caller owns policy. The quick-start example hands the signature structure to raw openssl_verify with manual DER handling — that is a signal, not a convenience wrapper. Specific risks:
TagManager; misconfigure it and COSE tags silently degrade to generic tags. Algorithm allow-listing, crit header handling, and key-to-algorithm binding are all caller responsibilities.RS1 (SHA-1) exists and only emits E_USER_WARNING unless acknowledgeInsecureAlgorithm: true is passed; a future major will throw. Policy must reject it, not rely on defaults.Ed448::isSupported() must be consulted rather than assumed.x5c certificate chain validation or trust-list resolution. For EU DCC / health-certificate verification, that is a second system you must build or buy.Key questions.
webauthn-lib instead).dependents: 0 / 19 stars a true adoption signal, or an artifact of this being a transitive dependency of webauthn-lib? Validate against Packagist download stats and composer why before treating popularity as a risk input.Stack fit. Laravel 10/11/12 on PHP 8.1+ is compatible. Bind a narrow interface pair in a dedicated service provider and publish a config file:
config/cose.php — allowed alg identifiers (positive allow-list, ES256/EdDSA/PS256 only), minimum/maximum RSA modulus (RsaKeyValidator::create(minimumModulusLength: 3072, maximumModulusLength: 8192)), max payload bytes, max CBOR depth, clock skew.CoseServiceProvider — registers the adapter as a singleton; inject the pre-built Decoder with the COSE TagManager configured once.Cose\* and CBOR\* imports inside app/Infrastructure/Cose/. Nothing above that layer should reference them.Migration path. Treat this as a read-path-first change, since verification is where the immediate business value sits:
ext-openssl and, if needed, ext-sodium.kid → key resolution, and RsaKeyValidator. Map library exceptions to domain exceptions at the boundary.Compatibility. Run composer why spomky-labs/cbor-php and brick/math before installing to detect version pin conflicts; the library has historically widened its brick/math constraint, so conflicts are unlikely but must be verified. Pin exact versions in composer.lock, enable Dependabot on this package specifically, and treat patch bumps as requiring a full test-suite pass given the crypto surface.
Sequencing. Interfaces → config/allow-list → key resolution + RSA validation → verify path with negative tests (wrong alg, truncated CBOR, oversized payload, missing tag manager) → sign path → observability → load test → runbook. Do not parallelize policy work with implementation; the allow-list is the security control and should be reviewed before code merges.
Maintenance. MIT, actively released (multiple minor releases adding RFC 9864 fully-specified identifiers and RFC 8812 key-size validation), maintained by Florent Morselli with a small contributor base. Bus factor is the dominant maintenance risk: one primary maintainer, no foundation backing. Mitigate with aggressive version pinning, a vendored-fork contingency plan, and by keeping the library confined to one adapter class so a swap is a contained change. Ongoing cost once integrated is genuinely low — a few hours per quarter for dependency review.
Support. Community-only: GitHub issues, a personal security email, no SLA. Acceptable for internal or non-regulated workloads; for regulated contexts (health certificates, document signing) document the escalation path and set an internal patch-SLA (e.g., 7 days for a crypto CVE) that does not depend on upstream responsiveness.
Scaling. Verification is CPU-bound and stateless, so horizontal scaling is trivial and there is no shared-state concern. Costs are predictable: ES256 verification is sub-millisecond to low-single-digit milliseconds; RSA-4096 and full x5c chain validation are the expensive paths and should be measured, not assumed. Two Laravel-specific notes: cache resolved public keys per request (or in a shared store) to avoid repeated parsing, and keep the adapter free of mutable instance state so it remains safe under Octane's long-lived workers.
Failure modes. Design each of these into the adapter and its tests:
alg → must fail closed, never fall through to a default.TagManager → silent misparse; assert tag types after decode.RsaKeyValidator must be invoked explicitly; the library never applies RFC 8812 bounds on its own.ext-openssl / ext-sodium in a container image → fatal at runtime; assert extensions at boot.Ed448::isSupported() and fail with a clear domain error.RS1) acceptance → an E_USER_WARNING in logs is not a control; exclude it at config level.Ramp-up. A mid-level PHP engineer reaches productivity on the API in one to two days — the surface is small and the README plus doc/Usage.md cover it. Real competence takes two to four weeks: understanding the Sig_structure construction, protected vs. unprotected header semantics, crit handling, and why algorithm-to-key binding matters. Plan for a security reviewer on the allow-list and header-validation code, and budget explicit time for writing negative tests — this is the rare package where the unhappy paths are the deliverable. Recommend pairing the initial integration with an RFC 9052 read-through; the docs are good but assume that context.
How can I help you explore Laravel packages today?