Syntactically, the signed xml is valid (conforms the schema indicated) and signature looks ok. However, it fails to validate both on the receiving end, and internally, using verify() call.
I extended the main class to enable debugging:
class XMLSecurityDSig extends \RobRichards\XMLSecLibs\XMLSecurityDSig
{
use enableZendLogging; // logging trait that allows formatted logging to file, consistent with the zf1 framework being used in the project
const LOG_NAME = 'xmldsig.log'; // default log name
The extended class has changes in the sign() method to see what is about to be signed, as follows:
public function sign($objKey, $appendToNode = null)
{
// If we have a parent node append it now so C14N properly works
if ($appendToNode != null) {$this->resetXPathObj();
$this->appendSignature($appendToNode);
$this->sigNode = $appendToNode->lastChild;
}
if ($xpath = $this->getXPathObj()) {
$query = "./secdsig:SignedInfo";
$nodeset = $xpath->query($query, $this->sigNode);
if ($sInfo = $nodeset->item(0)) {
$query = "./secdsig:SignatureMethod";
$nodeset = $xpath->query($query, $sInfo);
$sMethod = $nodeset->item(0);
$sMethod->setAttribute('Algorithm', $objKey->type);
$data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
$sigValue = base64_encode($this->signData($objKey, $data));
$sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
$this->debug(sprintf('%s: signed data={%s} for node=%s, cMethod=%s, signature={%s}',
__METHOD__,
$data,
$sInfo->nodeName,
$this->canonicalMethod,
$sigValue
));
if ($infoSibling = $sInfo->nextSibling) {
$infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
} else {
$this->sigNode->appendChild($sigValueNode);
}
}
}
(note the debug call)
The outer code calling the XMLSecurityDSig is as follows:
...
const DSIG_REF_OPTIONS = ['overwrite' => false, 'force_uri' => true]; // I do not need the Id attribute in the root node, as it violates the schema
// some irrelevant code skipped
protected function sign()
{
if(null === $this->dsig) {
$this->initDsig(); // initializes the dsig object with parameters
}
$objKey = $this->initDsigKey(); // load the private key and passphrase from the database
$this->insertThumbnail(); // inserts the thumbprint of the x.509 certificate matching the private key - Signature/KeyInfo/KeyName node
// $this->debug(sprintf('About to sign: %s, owned by %s', $this->dsig->sigNode->tagName, $this->dsig->sigNode->ownerDocument->tagName));
$this->dsig->sign($objKey, $this->dom->documentElement);
}
**Expected results:**
signed data outputs a canonicalized version of the original document, containing the <Merchant> block
**Actual results:**
signed data is the <Signature> block - it signs itself.
Am I doing something wrong? Or is it a bug I just found?
I am trying to sign an iDealPro DirectoryRequest xml as follows:
Syntactically, the signed xml is valid (conforms the schema indicated) and signature looks ok. However, it fails to validate both on the receiving end, and internally, using verify() call.
I extended the main class to enable debugging:
The extended class has changes in the sign() method to see what is about to be signed, as follows:
(note the debug call)
The outer code calling the XMLSecurityDSig is as follows: ...
const DSIG_REF_OPTIONS = ['overwrite' => false, 'force_uri' => true]; // I do not need the Id attribute in the root node, as it violates the schema // some irrelevant code skipped protected function sign() { if(null === $this->dsig) { $this->initDsig(); // initializes the dsig object with parameters } $objKey = $this->initDsigKey(); // load the private key and passphrase from the database $this->insertThumbnail(); // inserts the thumbprint of the x.509 certificate matching the private key - Signature/KeyInfo/KeyName node
// $this->debug(sprintf('About to sign: %s, owned by %s', $this->dsig->sigNode->tagName, $this->dsig->sigNode->ownerDocument->tagName)); $this->dsig->sign($objKey, $this->dom->documentElement); }