I have XML document:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<saml2p:ArtifactResolve xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Version="2.0"
IssueInstant="2020-06-01T10:25:15+02:00">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">TEST</saml2:Issuer>
<saml2p:Artifact>AAQAAKFbFR94fxqmioAqjJUwfHTFVHTDBTVHdBwwTW+ehcM19zsk=</saml2p:Artifact>
</saml2p:ArtifactResolve>
</soapenv:Body>
</soapenv:Envelope>
I try to do this in this way:
$results = array();
$filename = 'cert.p12';
$password = 'certpass';
$priv_key = openssl_pkcs12_read(file_get_contents($filename), $results, $password);
$doc = new DOMDocument();
$doc->loadXML($xml);
$xp = new DOMXPath($doc);
$xp->registerNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
$xp->registerNamespace('saml2p','urn:oasis:names:tc:SAML:2.0:protocol');
$xp->registerNamespace('saml2','urn:oasis:names:tc:SAML:2.0:assertion');
$xp->registerNamespace('ds',XMLSecurityDSig::XMLDSIGNS);
$artifactResolveNode = $xp->query('/*[local-name()=\'Envelope\']/*[local-name()=\'Body\']/*[local-name()=\'ArtifactResolve\']')->item(0);
if($artifactResolveNode){
$objDSig = new XMLSecurityDSig();
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$objDSig->addReference(
$artifactResolveNode,
XMLSecurityDSig::SHA256,
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/2001/10/xml-exc-c14n#'),
array('force_uri' => true)
);
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private'));
$objKey->loadKey($results['pkey'], FALSE);
$objDSig->sign($objKey);
$objDSig->add509Cert($results['cert']);
$objDSig->appendSignature($doc->documentElement());
echo $doc->saveXML();
}
Output with Singnature in wrong location is:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<saml2p:ArtifactResolve xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Version="2.0" IssueInstant="2020-06-01T10:25:15+02:00" Id="pfx97783ab1-0339-0f2e-b759-9e9c07e347b0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">TEST</saml2:Issuer><saml2p:Artifact>AAQAAKFbFR94fxqmioAqjJUwfyUtjJbv0uEPB7ooopodBwwTW+ehcM19zsk=</saml2p:Artifact></saml2p:ArtifactResolve>
</soapenv:Body>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
(...)
</soapenv:Envelope>
I want to put Signature node between ISSUER and ARTIFACT. This location is very important to correct send SOAP Envelope. It is possible?
I found! I need add code below:
$artifactNode = $xp->query('/*[local-name()=\'Envelope\']/*[local-name()=\'Body\']/*[local-name()=\'ArtifactResolve\']/*[local-name()=\'Artifact\']')->item(0);
and append Signature like this:
$objDSig->insertSignature($artifactResolveNode,$artifactNode);