Set URI attribute with a fixed value
Closed this issue · 4 comments
In
https://github.com/robrichards/xmlseclibs/blob/master/src/XMLSecurityDSig.php#L662
I needed to change the line to read
$refNode->setAttribute("URI", '#'.$id_name)
Because I was trying to reproduce an XML which has
<attachment id="attachmentId">[data]</attachment>
and below
<ds:Reference URI="#attachmentId">
Hello @robrichards!
I've the same question/issue.
I believe its already possible to sign a only a part of xml (with this libary) and it will get reflected in "Reference".
I'm looking for solution that will only sign a part of the xml file.
@sabas did you find a solution for this?
@BanalitoRaulito I was in a rush to complete the thing and I simply commented out the if block here
https://github.com/robrichards/xmlseclibs/blob/master/src/XMLSecurityDSig.php#L650
/*
if (! $node instanceof DOMDocument) {
$uri = null;
if (! $overwrite_id) {
$uri = $prefix_ns ? $node->getAttributeNS($prefix_ns, $id_name) : $node->getAttribute($id_name);
}
if (empty($uri)) {
$uri = self::generateGUID();
$node->setAttributeNS($prefix_ns, $attname, $uri);
}
$refNode->setAttribute("URI", '#'.$uri);
} elseif ($force_uri) {
$refNode->setAttribute("URI", '#'.$uri);
}
*/
$refNode->setAttribute("URI", '#'.$id_name);
I hope it helps somehow :-)
$doc = new \DOMDocument();
$doc->loadXML('hole xml content');
$element = $doc->getElementsByTagName('SignedProperties');
$objDSig = new XMLSecurityDSig();
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$objDSig->addReference(
$element[0],
XMLSecurityDSig::SHA256,
null,
[
'id_name' => 'id',
'overwrite' => true,
]
);
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'private']);
$objKey->loadKey(base_path(...), true);
$objDSig->sign($objKey);
$objDSig->add509Cert(file_get_contents(...));
$objDSig->appendSignature($doc->documentElement);
I managed to get it working!
The element in xml I wanted to sign is called "SignedProperties" and it has property id (note 'id_name' value in addReference).
addReference first value must be a DOMElement (not DOMDocument) to make use of this functionality.
Managed to review this after an upgrade broke again my patchwork :D
@BanalitoRaulito nice hint, that was the DOMElement, plus the id_name wasn't the one to be inserted in the document but the id of the existing element
In my case the xml to be signed contained this element
$attachment = $xml->createElement('attachment', $attachment1);
$attachment->setAttribute('id', 'attachmentId');
$root->appendChild($attachment);
And the correct way to sign this is
$objXMLSecDSig = new XmlSecurityDSig();
$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$objXMLSecDSig->addReference(
$xml->getElementsByTagName('attachment')[0],
XMLSecurityDSig::SHA256,
[
[
'http://www.w3.org/TR/1999/REC-xpath-19991116' => [
'query' => "*[@id='attachmentId']",
'namespaces' => [
'ds' => 'http://www.w3.org/2000/09/xmldsig#',
],
],
],
'http://www.w3.org/2000/09/xmldsig#enveloped-signature',
'http://www.w3.org/2001/10/xml-exc-c14n#WithComments',
],
[
'overwrite' => false,
'id_name' => 'id',
'prefix_ns' => false
]
);