Insertion modes
Signing an XML document produces a <Signature> element with the information of that signature. This element is included in
the XML following the defaults in the table below. You can also choose a custom location, as shown in
Setting where the signature element goes.
Default location of the signature node
| Signer | Default | Default without an XML document |
|---|---|---|
| @Lacuna.Pki.Xml.FullXmlSigner | Child of the root element | (Not applicable) |
| @Lacuna.Pki.Xml.XmlElementSigner | Sibling of the signed element | (Not applicable) |
| @Lacuna.Pki.Xml.OnlineResourceXmlSigner | Child of the root element | Root element |
| @Lacuna.Pki.Xml.DetachedResourceXmlSigner | Child of the root element | Root element |
The @Lacuna.Pki.Xml.FullXmlSigner and @Lacuna.Pki.Xml.XmlElementSigner signers require an XML document, so the Default without an XML document column does not apply to them.
To choose a custom location for the signature element, see the next section.
Setting where the signature element goes
In PKI SDK, you can choose where the signature element goes with the @Lacuna.Pki.Xml.XmlSigner.SetSignatureElementLocation(System.String,Lacuna.Pki.Xml.NamespaceManager,Lacuna.Pki.Xml.XmlInsertionOptions) method of the signers.
As an example, we sign the whole XML document below:
<invoice xmlns="http://www.lacunasoftware.com/sample">
<issuer>
<name>Lacuna Software Ltda EPP</name>
<fiscalCode>20658903000171</fiscalCode>
</issuer>
<customer>
<name>Banco do Brasil SA</name>
<fiscalCode>00000000000191</fiscalCode>
</customer>
<items>
<item>
<productCode>10201</productCode>
<description>Philips screws</description>
<quantity>100</quantity>
</item>
</items>
<signaturePlaceholder>
<!-- We want the signature to be inserted here -->
</signaturePlaceholder>
</invoice>
We want to sign the document above and put the signature element inside the <signaturePlaceholder> element. The code below
does that.
// Create a namespace manager with the necessary namespaces to
// get to the target element for the signature insertion
var nsm = new NamespaceManager();
nsm.AddNamespace("ls", "http://www.lacunasoftware.com/sample");
string xpath = "//ls:signaturePlaceholder"; // XPath to the target element
var signer = new FullXmlSigner();
signer.SetXml(lacunaInvoiceXmlBytes); // Set the XML document bytes
signer.SetPolicy(policy); // Set the signature policy
signer.SetSigningCertificate(cert); // Set the certificate with key
// Set the signature element location
signer.SetSignatureElementLocation(xpath, nsm, XmlInsertionOptions.AppendChild);
signer.ComputeSignature();
var signedXml = signer.GetSignedXml(); // Return signed XML
In the signed XML, the signature element is a child of the <signaturePlaceholder> element.
<invoice xmlns="http://www.lacunasoftware.com/sample">
...
<signaturePlaceholder>
<!-- We want the signature to be inserted here -->
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-fce02462-f2bd-4b7f-8def-f9c23b6672a2">
...
</Signature>
</signaturePlaceholder>
</invoice>
About the string xpath parameter of the
@Lacuna.Pki.Xml.XmlSigner.SetSignatureElementLocation(System.String,Lacuna.Pki.Xml.NamespaceManager,Lacuna.Pki.Xml.XmlInsertionOptions)
method: on the @Lacuna.Pki.Xml.XmlElementSigner signer, the XPath is evaluated from the element chosen for signing, while on the
other signers it is evaluated from the root element of the XML.