xmlseclibs.php
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
22, Aug 2026, 4.0.0
Features:
- Add reference option omit_uri to skip adding a URI attribute on Reference
  (also skips Id assignment on the referenced element, which exists only to
  support the URI fragment)
- Change selected XMLSecurityDSig private properties and methods to protected
  so the class can be extended (gdespirito). refs #152
- Add XMLSecurityDSig::ENVELOPED constant for the enveloped-signature Transform
  URI; deprecate empty appendCert() stub (use add509Cert())

Security Improvements:
- Harden add509Cert() URL fetching against SSRF: only http/https by default
  (file:// requires options['allow_file_scheme']); resolve the host and reject
  loopback/private/link-local/reserved/CGNAT addresses; disable HTTP redirects
- Reject IPv4-mapped / IPv4-compatible IPv6 certificate URL hosts (e.g.
  ::ffff:127.0.0.1, ::ffff:169.254.169.254): unwrap the embedded IPv4 and apply
  the same private/reserved/CGNAT checks (PHP's FILTER_FLAG_NO_* treats mapped
  addresses as public)
- Fail closed on unknown Reference Transform algorithms; recognize
  enveloped-signature explicitly. validateReference() no longer always detaches
  the Signature from the caller DOM (that broke C14N of ds:Object targets and
  left half-mutated trees on failure); enveloped-signature removes Signature
  only when it is a proper descendant of the node being digested
- Tighten same-document Reference URIs to empty URI and "#id" only (reject
  "?query", bare "#", and external URIs); share parsing between processRefNode()
  and getRefNodeID(). Same-document refs always omit comments
- Reject hostile idKeys attribute names (no whitespace / XPath operators) via
  Utils\XPath::filterAttrName; invalid names throw
- Reject duplicate CanonicalizationMethod / SignatureMethod under SignedInfo and
  duplicate DigestMethod / DigestValue / SignatureValue during verify
- Reset the cached DOMXPath in locateSignature() so instance reuse across
  documents cannot fatal with "Node from wrong document"
- verifyDocument() no longer permanently overwrites instance algorithm
  allowlists (restored in finally)
- addReference() / addReferenceList() / sign() / add509Cert() throw instead of
  silently no-oping when SignedInfo / signature context is missing; sign()
  requires setCanonicalMethod() and a SignatureMethod element
- Require correct namespace URIs for InclusiveNamespaces (exc-c14n) and XPath
  transform children (not localName alone)
- Reject a DOCTYPE in decrypted XML (defense against entity-expansion / XXE in
  attacker-crafted encrypted content)
- Reject a DOCTYPE in documents being signature-verified (locateSignature). Closes
  the entity-reference signature bypass where an Id="&e;" attribute is resolved by
  getAttribute() but invisible to the XPath reference lookup (libxml2
  xmlXPathNodeValHash bug, the CVE-2025-23369 root cause), letting verify()
  validate a different node than the application reads. Opt out with
  XMLSecurityDSig::$forbidDoctype = false
- Deny RSA-1.5 (PKCS#1 v1.5) key transport on decryption by default
  (Bleichenbacher / XML-Encryption backward-compatibility attack); opt in via
  XMLSecEnc::$allowRSA15KeyTransport. Add optional key-transport / data
  algorithm allowlists ($allowedKeyAlgorithms / $allowedDataAlgorithms, with
  DEFAULT_KEY_ALGORITHMS / DEFAULT_DATA_ALGORITHMS presets)
- Use a single generic "Failure decrypting Data" error for all decryption
  failures (bad padding, cipher error, failed RSA unwrap) so callers cannot
  build a CBC padding oracle from distinguishable errors. Catch and normalize
  phpseclib throws (LengthException, BadDecryptionException, RuntimeException,
  etc.) on symmetric and RSA decrypt paths so exception type/message cannot
  form a ciphertext-validity oracle either.
- Add verifyDocument(): safe-by-default signature verification that requires a
  caller-pinned key (never trusts KeyInfo), enforces a SignatureMethod/DigestMethod
  algorithm allowlist, fails closed on unvalidated references, and returns the
  validated node set. New $allowedSignatureAlgorithms / $allowedDigestAlgorithms
  properties (default strong: SHA-256+ digests, RSA-SHA-256+/PSS signatures);
  the low-level verify()/validateReference() primitives remain unrestricted for
  backward compatibility unless these properties are set (except the
  SignatureMethod/key-algorithm binding, which is always enforced -- see below).
- Reject asymmetric key material (X.509 certificate / PEM public key) being
  loaded as an HMAC key; prevents signature key/algorithm confusion forgery
- verify() now always binds the document's SignatureMethod to the algorithm of
  the supplied key (previously only when $allowedSignatureAlgorithms was set),
  so a mismatch is rejected even on the low-level path. Blocks algorithm
  substitution / key confusion (e.g. downgrading an RSA signature to hmac-sha1
  so a public key is used as the HMAC secret)
- Bound EncryptedKey / RetrievalMethod resolution depth (prevents recursive
  key-reference DoS / memory exhaustion)
- Reject XPath (REC-xpath-19991116) Transforms during verification by default.
  The transform evaluates a document-supplied XPath expression in 
  validateReference()  before any crypto runs, so a crafted expression is a 
  pre-auth CPU denial-of-service; the expression is arbitrary XPath by design 
  and cannot be sanitized. SAML / WS-Security do not use XPath transforms. Opt in
  with XMLSecurityDSig::$allowXPathTransforms = true. Signing is unaffected
- Cap XPath transforms (max 5) and namespaces per XPath transform (max 20);
  overridable via $maxXPathTransforms / $maxXPathNamespaces
- Fail closed on unresolved, external, and duplicate-Id Reference URIs
- Reject unknown CanonicalizationMethod algorithms
- Use hash_equals for digest and HMAC compares; HMAC verify returns 1/0
- Validate ISO 10126 pad length on CBC decrypt
- Harden decrypted XML parsing (LIBXML_NONET); restrict certificate URL fetches
- Use random_bytes for GUID generation

Features:
- Remove support for PHP < 8.0
- add support for RSA PSS (Julius Türich and joonlabs)
- use phpseclib for encrypting rsa-oaep and rsa-oaep-mgf1p 
  (Julius Türich and joonlabs)
- use phpseclib for all crypto (symmetric, RSA-1.5, RSA signatures,
  X.509); OpenSSL extension is now optional
- Add XMLSecurityDSig::setSignatureId() to set an Id on the Signature element
  without mutating sigNode directly
- Add enableLegacyMode() on XMLSecurityDSig and XMLSecEnc: one call restores
  pre-4.0 interoperability defaults (accept DOCTYPE, allow XPath transforms
  without count caps, allow RSA-1.5 key transport). Does not undo always-on
  cryptographic hardening (algorithm/key binding, uniform decrypt errors,
  hash_equals, decrypted-XML DOCTYPE rejection, etc.). Temporary migration aid.
- Make transforms element configurable with options array, default true
- Add optional $options constructor argument on XMLSecurityDSig; pass
  'stripWhitespace' => true (default false) to build signatures from a
  compact template with no whitespace between elements (BASE_TEMPLATE_NOWS)
- Add optional $options constructor argument on XMLSecEnc; pass
  'stripWhitespace' => true (default false) to build EncryptedData from a
  compact template with no whitespace between elements (template_NOWS)

Notes:
- Prefer RSA-OAEP and AES-GCM for new deployments; RSA-1.5 and CBC remain
  for legacy XML Encryption interoperability
- Always check verify() === 1; use getValidatedNodes() for SAML/WS-Security
- Do not trust KeyInfo certificates alone — pin or validate against a trust store
- Prefer secure defaults; use enableLegacyMode() only while migrating peers

Improvements:
- Fix deprecation notice in makeAsnSegment() under PHP 8.5
- Update parameter type in XMLSecurityDSig::addReference() and addRefInternal()
- Tighten XMLSecEnc PHPDoc types for algorithm allowlists, references, and
  encrypt/decrypt return values
- Harden XMLSecurityDSig DOM handling for static analysis: require DOMElement
  before attribute access on XPath results, correct locateSignature /
  reference / staticAdd509Cert PHPDocs, guard failed XPath queries and missing
  SignatureMethod nodes, and remove dead null comparisons

Bug Fixes:
- Compact signature template (XMLSecurityDSig 'stripWhitespace' option) removes
  inter-element whitespace that caused signature mismatch with C# SignedXml and
  Python signxml.
- Compact encryption template (XMLSecEnc 'stripWhitespace' option) removes
  inter-element whitespace from EncryptedData for peers that reject significant
  whitespace between elements.
- Guard XMLSecEnc encrypt/decrypt and EncryptedKey construction against null
  DOM nodes, uninitialized templates, and non-string crypto results that could
  fatal under PHP 8; prefer getAlgorithm() when writing EncryptionMethod

12, Dec 2025, 3.1.5
Security:
- Validate AES-GCM Authentication Tag (Sideni)

08, Dec 2025, 3.1.4
Security:
- fix canonicalization bypass error (d0ge)

20, Nov 2024, 3.1.3
Bug Fixes:
- remove loadKey check due to BC issues

20, Nov 2024, 3.1.2
Improvements:
- Add tab to list of whitespace values to remove from cert. refs #252
- loadKey should check return value for openssl_get_privatekey (sammarshallou)
- Switch to GitHub actions (SharkMachine)

05, Sep 2020, 3.1.1
Features:
- Support OAEP (iggyvolz)

Bug Fixes:
- Fix AES128 (iggyvolz)

Improvements:
- Fix tests for older PHP

22, Apr 2020, 3.1.0
Features:
- Support AES-GCM. Requires PHP 7.1. (François Kooman)

Improvements:
- Fix Travis tests for older PHP versions.
- Use DOMElement interface to fix some IDEs reporting documentation errors

Bug Fixes:
- FIX missing InclusiveNamespaces PrefixList from Java + Apache WSS4J. (njake)

06, Nov 2019, 3.0.4
Security Improvements:
- Insure only a single SignedInfo element exists within a signature during 
  verification. Refs CVE-2019-3465.
Bug Fixes:
- Fix variable casing.

15, Nov 2018, 3.0.3
Bug Fixes:
- Fix casing of class name. (Willem Stuursma-Ruwen)
- Fix Xpath casing. (Tim van Dijen)

Improvements:
- Make PCRE2 compliant. (Stefan Winter)
- Add PHP 7.3 support. (Stefan Winter)

27, Sep 2018, 3.0.2
Security Improvements:
- OpenSSL is now a requirement rather than suggestion. (Slaven Bacelic)
- Filter input to avoid XPath injection. (Jaime Pérez)

Bug Fixes:
- Fix missing parentheses (Tim van Dijen)

Improvements:
- Use strict comparison operator to compare digest values. (Jaime Pérez)
- Remove call to file_get_contents that doesn't even work. (Jaime Pérez)
- Document potentially dangerous return value behaviour. (Thijs Kinkhorst)

31, Aug 2017, 3.0.1
Bug Fixes:
- Fixed missing () in function call. (Dennis Væversted)

Improvements:
- Add OneLogin to supported software.
- Add .gitattributes to remove unneeded files. (Filippo Tessarotto)
- Fix bug in example code. (Dan Church)
- Travis: add PHP 7.1, move hhvm to allowed failures. (Thijs Kinkhorst)
- Drop failing extract-win-cert test (Thijs Kinkhorst). (Thijs Kinkhorst)
- Add comments to warn about return values of verify(). (Thijs Kinkhorst)
- Fix tests to properly check return code of verify(). (Thijs Kinkhorst)
- Restore support for PHP >= 5.4. (Jaime Pérez)

25, May 2017, 3.0.0
Improvements:
- Remove use of mcrypt (skymeyer)

08, Sep 2016, 2.0.1
Bug Fixes:
- Strip whitespace characters when parsing X509Certificate. fixes #84
  (klemen.bratec)
- Certificate 'subject' values can be arrays. fixes #80 (Andreas Stangl)
- HHVM signing node with ID attribute w/out namespace regenerates ID value.
  fixes #88 (Milos Tomic)

Improvements:
- Fix typos and add some PHPDoc Blocks. (gfaust-qb)
- Update lightSAML link. (Milos Tomic)
- Update copyright dates.

31, Jul 2015, 2.0.0
Features:
- Namespace support. Classes now in the RobRichards\XMLSecLibs\ namespace.

Improvements:
- Dropped support for PHP 5.2

31, Jul 2015, 1.4.1
Bug Fixes:
- Allow for large digest values that may have line breaks. fixes #62

Features:
- Support for locating specific signature when multiple exist in 
  document. (griga3k)

Improvements:
- Add optional argument to XMLSecurityDSig to define the prefix to be used, 
  also allowing for null to use no prefix, for the dsig namespace. fixes #13
- Code cleanup
- Depreciated XMLSecurityDSig::generate_GUID for XMLSecurityDSig::generateGUID

23, Jun 2015, 1.4.0
Features:
- Support for PSR-0 standard.
- Support for X509SubjectName. (Milos Tomic)
- Add HMAC-SHA1 support.

Improvements:
- Add how to install to README. (Bernardo Vieira da Silva)
- Code cleanup. (Jaime Pérez)
- Normalilze tests. (Hidde Wieringa)
- Add basic usage to README. (Hidde Wieringa)

21, May 2015, 1.3.2
Bug Fixes:
- Fix Undefined variable notice. (dpieper85)
- Fix typo when setting MimeType attribute. (Eugene OZ)
- Fix validateReference() with enveloping signatures

Features:
- canonicalizeData performance optimization. (Jaime Pérez)
- Add composer support (Maks3w)

19, Jun 2013, 1.3.1
Features:
- return encrypted node from XMLSecEnc::encryptNode() when replace is set to 
  false. (Olav)
- Add support for RSA SHA384 and RSA_SHA512 and SHA384 digest. (Jaime Prez)
- Add options parameter to the add cert methods.
- Add optional issuerSerial creation with cert

Bug Fixes:
- Fix persisted Id when namespaced. (Koen Thomeer)

Improvements:
- Add LICENSE file
- Convert CHANGELOG.txt to UTF-8

26, Sep 2011, 1.3.0
Features:
- Add param to append sig to node when signing. Fixes a problem when using 
  inclusive canonicalization to append a signature within a namespaced subtree.
  ex. $objDSig->sign($objKey, $appendToNode);
- Add ability to encrypt by reference
- Add support for refences within an encrypted key
- Add thumbprint generation capability (XMLSecurityKey->getX509Thumbprint() and 
  XMLSecurityKey::getRawThumbprint($cert))
- Return signature element node from XMLSecurityDSig::insertSignature() and 
  XMLSecurityDSig::appendSignature() methods
- Support for <ds:RetrievalMethod> with simple URI Id reference.
- Add XMLSecurityKey::getSymmetricKeySize() method (Olav)
- Add XMLSecEnc::getCipherValue() method (Olav)
- Improve XMLSecurityKey:generateSessionKey() logic (Olav)

Bug Fixes:
- Change split() to explode() as split is now depreciated
- ds:References using empty or simple URI Id reference should never include 
  comments in canonicalized data.
- Make sure that the elements in EncryptedData are emitted in the correct 
  sequence.

11 Jan 2010, 1.2.2
Features:
- Add support XPath support when creating signature. Provides support for 
  working with EBXML documents.
- Add reference option to force creation of URI attribute. For use
  when adding a DOM Document where by default no URI attribute is added.
- Add support for RSA-SHA256

Bug Fixes:
- fix bug #5: createDOMDocumentFragment() in decryptNode when data is node 
  content (patch by Francois Wang)


08 Jul 2008, 1.2.1
Features:
- Attempt to use mhash when hash extension is not present. (Alfredo Cubitos).
- Add fallback to built-in sha1 if both hash and mhash are not available and 
  throw error for other for other missing hashes. (patch by Olav Morken).
- Add getX509Certificate method to retrieve the x509 cert used for Key. 
  (patch by Olav Morken).
- Add getValidatedNodes method to retrieve the elements signed by the 
  signature. (patch by Olav Morken).
- Add insertSignature method for precision signature insertion. Merge 
  functionality from appendSignature in the process. (Olav Morken, Rob).
- Finally add some tests

Bug Fixes:
- Fix canonicalization for Document node when using PHP < 5.2.
- Add padding for RSA_SHA1. (patch by Olav Morken).


27 Nov 2007, 1.2.0
Features:
- New addReference/List option (overwrite). Boolean flag indicating if URI
  value should be overwritten if already existing within document.
  Default is TRUE to maintain BC.

18 Nov 2007, 1.1.2
Bug Fixes:
- Remove closing PHP tag to fix extra whitespace characters from being output

11 Nov 2007, 1.1.1
Features:
- Add getRefNodeID() and getRefIDs() methods missed in previous release.
  Provide functionality to find URIs of existing reference nodes.
  Required by simpleSAMLphp project

Bug Fixes:
- Remove erroneous whitespace causing issues under certain circumastances.

18 Oct 2007, 1.1.0
Features:
- Enable creation of enveloping signature. This allows the creation of
  managed information cards.
- Add addObject method for enveloping signatures.
- Add staticGet509XCerts method. Chained certificates within a PEM file can
  now be added within the X509Data node.
- Add xpath support within transformations.
- Add InclusiveNamespaces prefix list support within exclusive transformations.

Bug Fixes:
- Initialize random number generator for mcrypt_create_iv. (Joan Cornadó).
- Fix an interoperability issue with .NET when encrypting data in CBC mode.
  (Joan Cornadó).
