robrichards/xmlseclibs
xmlseclibs is a PHP library for XML Encryption and Signatures, offering safe-by-default verification, pinned keys, algorithm allowlists, RSA-OAEP/AES-GCM support, and low-level primitives for legacy XML security workflows.
openssl_verify in application code is where signature-wrapping, KeyInfo trust, and canonicalization bugs live. This package is the "buy" option for the cryptographic core, and it is the same core already under SimpleSAMLphp, OneLogin php-saml, and LightSAML, so choosing it is choosing the ecosystem default rather than a novel dependency.enableLegacyMode(), allowRSA15KeyTransport, allowXPathTransforms), which means each interop concession can be tracked as a named, owned, expiring roadmap item rather than an invisible weakening of the whole system.master, but a single primary author and a 4.0 line still in beta with documented breaking defaults (3.1 → 4.0). That shapes version-pinning policy, upgrade budgeting, and the risk register entry.Adopt when most of these hold:
verifyDocument() expects exactly this.phpseclib/phpseclib ~3.0 (with OpenSSL optional — useful in locked-down images without ext-openssl).wsu:Id-style attribute namespaces) rather than a batteries-included SAML stack.Look elsewhere when:
For executives: This is a small, permissively licensed dependency that replaces a class of security work we would otherwise have to design, build, and audit ourselves — XML signature verification and XML encryption for partner integrations. It absorbs attack classes we would not have scoped (signature wrapping, entity-reference resolution bypass, padding-oracle decryption, SSRF via certificate URLs) as defaults, not optional hardening. It is already the cryptographic foundation under the major PHP SAML implementations, so we are standardizing on the ecosystem's shared core instead of a bespoke one. Cost is essentially integration effort, not licensing; the real investment is our own key management and a thin Laravel adapter, both of which we would need anyway.
For engineering: Treat verifyDocument() with a pinned key as the only sanctioned verification path; operate solely on the returned validated nodes and never re-select assertions by Id from the full document. Low-level primitives are allowed for signing and for workflows that genuinely need them, with the rule that verify() results are compared === 1 and decrypt failures are never branched on by message. Pin the algorithm allowlists explicitly, keep legacy mode behind a config flag with an owner and an expiry date, and instrument it — every use of legacy mode, RSA-1.5, or CBC is a metric we watch and a migration ticket. Certificate fetching is blocking network I/O: queue it, never inline in a request. Version-pin in Composer; 4.0 is still beta with intentional breaking defaults, so plan a dedicated upgrade window rather than a floating constraint.
Risks to state out loud, once: single primary maintainer on a security-critical path (mitigate with pinned versions, an internal review of the verification path, and a tested fallback plan); a metric showing zero dependents that contradicts documented real-world usage, so verify transitive adoption yourself before treating it as a signal; and known breaking changes between 3.1 and 4.0 — decide now whether you ship on 3.1 hardened defaults or commit to the 4.0 line, and put the migration on the roadmap rather than discovering it.
How can I help you explore Laravel packages today?