robrichards / xmlseclibs

A PHP library for XML Security
BSD 3-Clause "New" or "Revised" License
390 stars 181 forks source link

Problem signing XML with namespaces #264

Open KevinVG opened 1 month ago

KevinVG commented 1 month ago

We are having an issue signing XML with namespaces. Simplified code example:

        $xml = '<?xml version="1.0"?><smp:SignedServiceMetadata xmlns:smp="http://busdox.org/serviceMetadata/publishing/1.0/"><smp:ServiceMetadata></smp:ServiceMetadata></smp:SignedServiceMetadata>';
        $doc = new \DOMDocument();
        $doc->loadXML($xml);

        $privateKey = '...';
        $certificate = '...';
        $passphrase = '...';

        $DSig = new XMLSecurityDSig();
        $DSig->setCanonicalMethod(XMLSecurityDSig::C14N);
        $DSig->addReference(
            $doc,
            XMLSecurityDSig::SHA256,
            ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],
            ['force_uri' => true]
        );
        // Create a new (private) Security key
        $key = new XMLSecurityKey(
            XMLSecurityKey::RSA_SHA256,
            ['type' => 'private', 'passphrase' => $passphrase]
        );
        // Load the private key
        $key->loadKey($privateKey);

        // Add the associated public key to the signature
        $DSig->add509Cert($certificate, true, false, ['subjectName' => true]);

        // Sign the XML file
        $DSig->sign($key);

        $DSig->appendSignature($doc->documentElement);

        $signedXml = $doc->saveXML();

Gives an invalid signature. ( Tool used to check: https://tools.chilkat.io/xmlDsigVerify.cshtml )

Changing the xml input to input without namespaces works:

$xml = '<?xml version="1.0"?><SignedServiceMetadata><ServiceMetadata></ServiceMetadata></SignedServiceMetadata>';
tvdijen commented 1 month ago

They're both invalid when I try and verify the above. It's not adding a proper reference URI, so the validator-tool will be unable to know what to verify

KevinVG commented 1 month ago

example1.txt example2.txt

Output of both example in attachment. Example 2 output is "Signature Verified".

Empty reference URI should be OK since the correct examples of what we are building also have an empty reference URI: http://b-7ded761b0d6131bbb582adc71de89513.iso6523-actorid-upis.edelivery.tech.ec.europa.eu/iso6523-actorid-upis%3A%3A9925%3Abe0714992641/services/busdox-docid-qns%3A%3Aurn%3Aoasis%3Anames%3Aspecification%3Aubl%3Aschema%3Axsd%3AApplicationResponse-2%3A%3AApplicationResponse%23%23urn%3Afdc%3Apeppol.eu%3Apoacc%3Atrns%3Amlr%3A3%3A%3A2.1 (also )

KevinVG commented 1 month ago

We were able to fix the issue by replacing:

        // Sign the XML file
        $DSig->sign($key);
        $DSig->appendSignature($doc->documentElement);

With

        $DSig->sign($key, $doc->documentElement);