robrichards/xmlseclibs
PHP library for XML Digital Signatures and XML Encryption. Create, sign, and verify XML (e.g., RSA-SHA256), manage keys and X.509 certs, and apply canonicalization/transforms. Widely used in SAML stacks like SimpleSAMLPHP and OneLogin.
Installation: Add the package via Composer:
composer require robrichards/xmlseclibs
Ensure your project uses PHP 8.0+ (required for the latest features).
First Use Case: Sign an XML document with a private key and append the signature:
use RobRichards\XMLSecLibs\XMLSecurityDSig;
use RobRichards\XMLSecLibs\XMLSecurityKey;
// Load XML
$doc = new DOMDocument();
$doc->load('document.xml');
// Initialize signer
$signer = new XMLSecurityDSig();
$signer->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$signer->addReference($doc, XMLSecurityDSig::SHA256, ['http://www.w3.org/2000/09/xmldsig#enveloped-signature']);
// Load private key
$key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'private']);
$key->loadKey('private_key.pem');
// Sign and append
$signer->sign($key);
$signer->appendSignature($doc->documentElement);
$doc->save('signed_document.xml');
Where to Look First:
spatie/laravel-xml-security) or create a service class to encapsulate XMLSecurityDSig/XMLSecurityKey logic.Encapsulate xmlseclibs in a Laravel service to abstract cryptographic operations:
// app/Services/XMLSecurityService.php
namespace App\Services;
use RobRichards\XMLSecLibs\XMLSecurityDSig;
use RobRichards\XMLSecLibs\XMLSecurityKey;
class XMLSecurityService
{
public function signXml(string $xmlPath, string $privateKeyPath, string $certPath): string
{
$doc = new \DOMDocument();
$doc->load($xmlPath);
$signer = new XMLSecurityDSig();
$signer->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$signer->addReference($doc, XMLSecurityDSig::SHA256, ['http://www.w3.org/2000/09/xmldsig#enveloped-signature']);
$key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'private']);
$key->loadKey($privateKeyPath);
$signer->sign($key);
$signer->add509Cert(file_get_contents($certPath));
$signer->appendSignature($doc->documentElement);
return $doc->saveXML();
}
}
Usage in Controller:
use App\Services\XMLSecurityService;
class XmlController extends Controller
{
public function sign(XMLSecurityService $service)
{
$signedXml = $service->signXml(
'document.xml',
storage_path('keys/private.pem'),
storage_path('keys/cert.pem')
);
return response()->xml($signedXml);
}
}
For encrypting XML content (e.g., sensitive payloads):
use RobRichards\XMLSecLibs\XMLSecurityEnc;
use RobRichards\XMLSecLibs\XMLSecurityKey;
$doc = new \DOMDocument();
$doc->load('data.xml');
// Encrypt a node
$enc = new XMLSecurityEnc();
$enc->setKey($this->getPublicKey()); // Load public key
$enc->encryptNode($doc->getElementsByTagName('sensitive-data')->item(0));
$doc->save('encrypted.xml');
Key Management:
Use Laravel’s config or environment variables for key paths:
// config/xmlsecurity.php
return [
'private_key' => storage_path('keys/private.pem'),
'public_key' => storage_path('keys/public.pem'),
'certificate' => storage_path('keys/cert.pem'),
];
Validate signatures in incoming XML (e.g., API requests):
public function validateSignature(XMLSecurityService $service, string $xml)
{
$doc = new \DOMDocument();
$doc->loadXML($xml);
$validator = new XMLSecurityDSig();
$validator->idKeys(); // Auto-load keys from XML
$validator->canonicalize($doc);
$result = $validator->checkSignature($doc->documentElement, true);
if (!$result) {
throw new \RuntimeException('Invalid signature');
}
}
Leverage AES-GCM (PHP 7.1+) for secure token encryption:
use RobRichards\XMLSecLibs\XMLSecurityKey;
$key = new XMLSecurityKey(XMLSecurityKey::AES256_GCM);
$key->generateSessionKey(); // Auto-generate key
$iv = openssl_random_pseudo_bytes(12); // GCM IV length
$encrypted = openssl_encrypt(
'sensitive-data',
'AES-256-GCM',
$key->key,
OPENSSL_RAW_DATA,
$iv
);
$tag = openssl_get_cipher_data($encrypted)['auth_tag']; // Store tag for validation
Decryption with Tag Validation:
$decrypted = openssl_decrypt(
$encrypted,
'AES-256-GCM',
$key->key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
if ($decrypted === false) {
throw new \RuntimeException('Invalid AES-GCM tag');
}
Protect routes requiring signed XML:
// app/Http/Middleware/ValidateXmlSignature.php
public function handle($request, Closure $next)
{
if ($request->isXml()) {
$this->validateSignature($request->xml());
}
return $next($request);
}
Key Management:
config or environment variables. For production, integrate with a secrets manager (e.g., AWS KMS, HashiCorp Vault).Canonicalization Mismatches:
EXC_C14N but validating with C14N (or vice versa) causes signature failures.$signer->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$validator->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
AES-GCM Tag Validation:
AUTH_TAG) leaves encrypted data vulnerable to silent corruption.true to openssl_decrypt() for tag validation:
$decrypted = openssl_decrypt($data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag, $tag);
DOMDocument Quirks:
LIBXML_NOBLANKS when loading XML:
$doc->loadXML($xml, LIBXML_NOBLANKS);
PHP OpenSSL Requirements:
if (!in_array('AES-256-GCM', openssl_get_cipher_methods())) {
throw new \RuntimeException('AES-GCM not supported');
}
Signature Validation Failures:
$validator->debug = true;
$validator->checkSignature($doc);
AES-GCM Errors:
if (strlen($iv) !== 12) {
throw new \RuntimeException('IV must be 12 bytes for GCM');
}
OPENSSL_RAW_DATA flag is used forHow can I help you explore Laravel packages today?