1import{_ as l,r as i,o as u,c as r,b as s,d as a,a as t,w as c,e as p}from"./app-4488e322.js";const d={},k={href:"https://jameslan.github.io/libxml2-wasm/v0.7/classes/libxml2-wasm.XmlDocument.html#canonicalizeToString",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/xmldom/xmldom",target:"_blank",rel:"noopener noreferrer"},g={href:"https://ec.europa.eu/digital-building-blocks/DSS/webapp-demo/doc/dss-documentation.html",target:"_blank",rel:"noopener noreferrer"};function v(h,n){const o=i("RouterLink"),e=i("ExternalLinkIcon");return u(),r("div",null,[n[18]||(n[18]=s("h1",{id:"direct-e-sealing-xades-reference-digest-request",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#direct-e-sealing-xades-reference-digest-request","aria-hidden":"true"},"#"),a(" Direct e-Sealing XAdES reference-digest Request")],-1)),n[19]||(n[19]=s("p",null,"Create an enveloped XAdES Baseline-LT e-seal while keeping the original XML in your system. Your integration calculates the XML document digest, sends it to eID Easy, and inserts the returned signature into the original XML.",-1)),s("p",null,[n[1]||(n[1]=a("Use the same endpoint, client setup and ",-1)),t(o,{to:"/e-seal/direct-e-sealing-api.html#authentication"},{default:c(()=>[...n[0]||(n[0]=[a("HMAC authentication",-1)])]),_:1}),n[2]||(n[2]=a(" as the other Cloud Direct e-Sealing requests:",-1))]),n[20]||(n[20]=p(`<div class="language-text line-numbers-mode" data-ext="text"><pre class="language-text"><code>POST https://id.eideasy.com/api/signatures/e-seal 2</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>For testing, use <code>https://test.eideasy.com/api/signatures/e-seal</code>.</p><h2 id="flow" tabindex="-1"><a class="header-anchor" href="#flow" aria-hidden="true">#</a> Flow</h2><ol><li><strong>Integrator:</strong> canonicalize the unsigned XML and calculate its SHA-256 document digest.</li><li><strong>eID Easy:</strong> create the XAdES Baseline-LT signature, including the signature timestamp and validation material, and return a standalone XML signature fragment.</li><li><strong>Integrator:</strong> insert the fragment into the original XML and validate the completed document.</li></ol>`,4)),s("table",null,[n[7]||(n[7]=s("thead",null,[s("tr",null,[s("th",null,"XAdES input"),s("th",null,"Request field"),s("th",null,[a("Response "),s("code",null,"signatures[].fileContent")])])],-1)),s("tbody",null,[s("tr",null,[s("td",null,[t(o,{to:"/e-seal/direct-e-sealing-xades-full-file-request.html"},{default:c(()=>[...n[3]||(n[3]=[a("Full XML file",-1)])]),_:1})]),n[4]||(n[4]=s("td",null,[s("code",null,"fileContent"),a(": Base64 original XML")],-1)),n[5]||(n[5]=s("td",null,"Base64 complete signed XML",-1))]),n[6]||(n[6]=s("tr",null,[s("td",null,"Document reference digest"),s("td",null,[s("code",null,"documentDigest"),a(": Base64 SHA-256 digest of canonicalized XML")]),s("td",null,[a("Base64 standalone "),s("code",null,"ds:Signature"),a(" fragment")])],-1))])]),n[21]||(n[21]=p(`<p>Both modes use <code>XAdES_BASELINE_LT</code> and <code>ENVELOPED</code>. The input field selects the mode; packaging describes the final signature structure.</p><h2 id="request-body" tabindex="-1"><a class="header-anchor" href="#request-body" aria-hidden="true">#</a> Request body</h2><div class="language-json line-numbers-mode" data-ext="json"><pre class="language-json"><code><span class="token punctuation">{</span> 3 <span class="token property">"client_id"</span><span class="token operator">:</span> <span class="token string">"client-id"</span><span class="token punctuation">,</span> 4 <span class="token property">"files"</span><span class="token operator">:</span> <span class="token punctuation">[</span> 5 <span class="token punctuation">{</span> 6 <span class="token property">"fileName"</span><span class="token operator">:</span> <span class="token string">"document.xml"</span><span class="token punctuation">,</span> 7 <span class="token property">"documentDigest"</span><span class="token operator">:</span> <span class="token string">"<Base64 SHA-256 digest of canonicalized XML>"</span><span class="token punctuation">,</span>
8 <span class="token property">"mimeType"</span><span class="token operator">:</span> <span class="token string">"application/xml"</span> 9 <span class="token punctuation">}</span> 10 <span class="token punctuation">]</span><span class="token punctuation">,</span> 11 <span class="token property">"signature_form"</span><span class="token operator">:</span> <span class="token string">"XAdES"</span><span class="token punctuation">,</span> 12 <span class="token property">"signature_profile"</span><span class="token operator">:</span> <span class="token string">"XAdES_BASELINE_LT"</span><span class="token punctuation">,</span> 13 <span class="token property">"signature_packaging"</span><span class="token operator">:</span> <span class="token string">"ENVELOPED"</span> 14<span class="token punctuation">}</span> 15</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Replace the digest placeholder with the value calculated from your XML.</p><table><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>client_id</td><td>string</td><td><strong>Required.</strong> Your eID Easy API client ID.</td></tr><tr><td>files</td><td>array</td><td><strong>Required.</strong> Between 1 and 30 files, all using <code>documentDigest</code>.</td></tr><tr><td>files[].fileName</td><td>string</td><td><strong>Required.</strong> Original file name, at least 3 characters, ending in <code>.xml</code> (case-insensitive). Unique within the request.</td></tr><tr><td>files[].documentDigest</td><td>string</td><td><strong>Required.</strong> Standard padded Base64 encoding of the 32-byte SHA-256 document digest: exactly 44 characters.</td></tr><tr><td>files[].mimeType</td><td>string</td><td><strong>Required.</strong> <code>application/xml</code>.</td></tr><tr><td>signature_form</td><td>string</td><td><strong>Required.</strong> <code>XAdES</code>.</td></tr><tr><td>signature_profile</td><td>string</td><td><strong>Required.</strong> <code>XAdES_BASELINE_LT</code>.</td></tr><tr><td>signature_packaging</td><td>string</td><td><strong>Required.</strong> <code>ENVELOPED</code>.</td></tr></tbody></table><p>Each file must contain exactly one of <code>documentDigest</code> or <code>fileContent</code>. A request cannot mix digest input and full-file input. <code>documentDigest</code> is supported only for XAdES. Do not send <code>digest_profile</code>; the canonicalization and digest algorithm are fixed.</p><h2 id="response-example" tabindex="-1"><a class="header-anchor" href="#response-example" aria-hidden="true">#</a> Response example</h2><div class="language-json line-numbers-mode" data-ext="json"><pre class="language-json"><code><span class="token punctuation">{</span> 16 <span class="token property">"status"</span><span class="token operator">:</span> <span class="token string">"OK"</span><span class="token punctuation">,</span> 17 <span class="token property">"signatures"</span><span class="token operator">:</span> <span class="token punctuation">[</span> 18 <span class="token punctuation">{</span> 19 <span class="token property">"fileName"</span><span class="token operator">:</span> <span class="token string">"document.xml"</span><span class="token punctuation">,</span> 20 <span class="token property">"mimeType"</span><span class="token operator">:</span> <span class="token string">"application/xml"</span><span class="token punctuation">,</span> 21 <span class="token property">"fileContent"</span><span class="token operator">:</span> <span class="token string">"<Base64 standalone ds:Signature XML fragment>"</span> 22 <span class="token punctuation">}</span> 23 <span class="token punctuation">]</span> 24<span class="token punctuation">}</span> 25</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>fileContent</code> contains the complete XML signature element, including its XAdES properties and LT material. It does not contain the original XML document. Insert the entire decoded element; do not extract only <code>SignatureValue</code>.</p><h2 id="digest-calculation" tabindex="-1"><a class="header-anchor" href="#digest-calculation" aria-hidden="true">
25#</a> Digest calculation</h2><p>The digest is the value for the signature's document reference (<code>URI=""</code>). It is <strong>not a hash of the raw XML file bytes</strong> and is not a <code>SignedInfo</code> digest.</p><p>The document reference uses these transforms, in order:</p><ol><li>Enveloped signature: <code>http://www.w3.org/2000/09/xmldsig#enveloped-signature</code>.</li><li>Exclusive XML Canonicalization 1.0 without comments: <code>http://www.w3.org/2001/10/xml-exc-c14n#</code>, with no inclusive namespace prefix list.</li></ol><p>Start with unsigned XML, so there is no signature to remove at preparation time. Canonicalize the <strong>whole document</strong>, including processing instructions outside the root element. Hash the resulting UTF-8 bytes with SHA-256, then Base64-encode the binary digest.</p><p>Keep the original XML for the insertion step. Changes to text, whitespace, namespace prefixes or document structure after calculating the digest can invalidate the signature.</p><h2 id="javascript-example" tabindex="-1"><a class="header-anchor" href="#javascript-example" aria-hidden="true">#</a> JavaScript example</h2>`,16)),s("p",null,[n[10]||(n[10]=a("This server-side Node.js example uses ",-1)),s("a",k,[n[8]||(n[8]=a("libxml2-wasm",-1)),t(e)]),n[11]||(n[11]=a(" for whole-document canonicalization and ",-1)),s("a",m,[n[9]||(n[9]=a("@xmldom/xmldom",-1)),t(e)]),n[12]||(n[12]=a(" for signature insertion. Run it with Node.js 22 or later.",-1))]),n[22]||(n[22]=p(`<div class="language-bash line-numbers-mode" data-ext="sh"><pre class="language-bash"><code><span class="token function">npm</span> <span class="token function">install</span> [email protected] @xmldom/[email protected] 26</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>The example assumes a validated, unsigned UTF-8 XML 1.0 document, without DTD/entity declarations or XInclude. If your document format has an XML schema, use it to validate the XML structure and determine the permitted signature location.</p><h3 id="_1-prepare-the-document-digest" tabindex="-1"><a class="header-anchor" href="#_1-prepare-the-document-digest" aria-hidden="true">#</a> 1. Prepare the document digest</h3><p>Save the following snippets together as <code>seal-xml.mjs</code>. Place the original XML in <code>document.xml</code>.</p><div class="language-javascript line-numbers-mode" data-ext="js"><pre class="language-javascript"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> readFile<span class="token punctuation">,</span> writeFile <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'node:fs/promises'</span><span class="token punctuation">;</span> 27<span class="token keyword">import</span> <span class="token punctuation">{</span> createHash<span class="token punctuation">,</span> createHmac <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'node:crypto'</span><span class="token punctuation">;</span> 28<span class="token keyword">import</span> <span class="token punctuation">{</span> XmlDocument<span class="token punctuation">,</span> XmlC14NMode <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'libxml2-wasm'</span><span class="token punctuation">;</span> 29<span class="token keyword">import</span> <span class="token punctuation">{</span> DOMParser<span class="token punctuation">,</span> XMLSerializer <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@xmldom/xmldom'</span><span class="token punctuation">;</span> 30 31<span class="token keyword">function</span> <span class="token function">createDocumentDigest</span><span class="token punctuation">(</span><span class="token parameter">unsignedXml</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 32 <span class="token keyword">const</span> document <span class="token operator">=</span> XmlDocument<span class="token punctuation">.</span><span class="token function">fromString</span><span class="token punctuation">(</span>unsignedXml<span class="token punctuation">)</span><span class="token punctuation">;</span> 33 34 <span class="token keyword">try</span> <span class="token punctuation">{</span> 35 <span class="token keyword">const</span> canonicalXml <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">canonicalizeToString</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
36 <span class="token literal-property property">mode</span><span class="token operator">:</span> XmlC14NMode<span class="token punctuation">.</span><span class="token constant">XML_C14N_EXCLUSIVE_1_0</span><span class="token punctuation">,</span> 37 <span class="token literal-property property">withComments</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> 38 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 39 40 <span class="token keyword">return</span> <span class="token function">createHash</span><span class="token punctuation">(</span><span class="token string">'sha256'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>canonicalXml<span class="token punctuation">,</span> <span class="token string">'utf8'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">digest</span><span class="token punctuation">(</span><span class="token string">'base64'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 41 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span> 42 document<span class="token punctuation">.</span><span class="token function">dispose</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 43 <span class="token punctuation">}</span> 44<span class="token punctuation">}</span> 45 46<span class="token keyword">const</span> fileName <span class="token operator">=</span> <span class="token string">'document.xml'</span><span class="token punctuation">;</span> 47<span class="token keyword">const</span> unsignedXml <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">readFile</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> <span class="token string">'utf8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 48<span class="token keyword">const</span> documentDigest <span class="token operator">=</span> <span class="token function">createDocumentDigest</span><span class="token punctuation">(</span>unsignedXml<span class="token punctuation">)</span><span class="token punctuation">;</span> 49</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_2-request-the-signature" tabindex="-1"><a class="header-anchor" href="#_2-request-the-signature" aria-hidden="true">#</a> 2. Request the signature</h3><p>Provide <code>EIDEASY_CLIENT_ID</code> and <code>EIDEASY_ESEAL_HMAC_KEY</code> through your server's environment or secret manager. Use the e-seal HMAC key, not the OAuth client secret. Keep it server-side.</p><div class="language-javascript line-numbers-mode" data-ext="js"><pre class="language-javascript"><code><span class="token keyword">const</span> endpoint <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">URL</span><span class="token punctuation">(</span><span class="token string">'
49https://test.eideasy.com/api/signatures/e-seal'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 50<span class="token keyword">const</span> clientId <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">EIDEASY_CLIENT_ID</span><span class="token punctuation">;</span> 51<span class="token keyword">const</span> hmacKey <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">EIDEASY_ESEAL_HMAC_KEY</span><span class="token punctuation">;</span> 52 53<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>clientId <span class="token operator">||</span> <span class="token operator">!</span>hmacKey<span class="token punctuation">)</span> <span class="token punctuation">{</span> 54 <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'Missing eID Easy client ID or e-seal HMAC key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 55<span class="token punctuation">}</span> 56 57<span class="token keyword">const</span> body <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span><span class="token punctuation">{</span> 58 <span class="token literal-property property">client_id</span><span class="token operator">:</span> clientId<span class="token punctuation">,</span> 59 <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> fileName<span class="token punctuation">,</span> documentDigest<span class="token punctuation">,</span> <span class="token literal-property property">mimeType</span><span class="token operator">:</span> <span class="token string">'application/xml'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> 60 <span class="token literal-property property">signature_form</span><span class="token operator">:</span> <span class="token string">'XAdES'</span><span class="token punctuation">,</span> 61 <span class="token literal-property property">signature_profile</span><span class="token operator">:</span> <span class="token string">'XAdES_BASELINE_LT'</span><span class="token punctuation">,</span> 62 <span class="token literal-property property">signature_packaging</span><span class="token operator">:</span> <span class="token string">'ENVELOPED'</span><span class="token punctuation">,</span> 63<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 64<span class="token keyword">const</span> timestamp <span class="token operator">=</span> <span class="token function">String</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 65<span class="token keyword">const</span> hmac <span class="token operator">=</span> <span class="token function">createHmac</span><span class="token punctuation">(</span><span class="token string">'sha256'</span><span class="token punctuation">,</span> hmacKey<span class="token punctuation">)</span> 66 <span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">\`</span><span class="token string">POST</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">\${</span>endpoint<span class="token punctuation">.</span>pathname<span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">\${</span>timestamp<span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">\${</span>body<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">\`</span></span><span class="token punctuation">,</span> <span class="token string">'utf8'</span><span class="token punctuation">)</span> 67 <span class="token punctuation">.</span><span class="token function">digest</span><span class="token punctuation">(</span><span class="token string">'base64'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 68 69<span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>endpoint<span class="token punctuation">,</span> <span class="token punctuation">{</span> 70 <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'POST'</span><span class="token punctuation">,</span> 71 <span class="token literal-property property">headers</span><span class="token operator">:</span> <span class="token punctuation">{</span> 72 <span class="token string-property property">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'application/json'</span><span class="token punctuation">,</span> 73 <span class="token string-property property">'X-Timestamp'</span><span class="token operator">:</span> timestamp<span class="token punctuation">,</span> 74 <span class="token string-property property">'X-HMAC-Signature'</span><span class="token operator">:</span> hmac<span class="token punctuation">,</span> 75 <span class="token punctuation">}</span><span class="token punctuation">,</span> 76 body<span class="token punctuation">,</span> 77<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 78 79<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>response<span class="token punctuation">.</span>ok<span class="token punctuation">)</span> <span class="token punctuation">{</span> 80 <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">\`</span><span class="token string">e-Sealing request failed with HTTP </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">\${</span>response<span class="token punctuation">.</span>status<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">\`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> 81<span class="token punctuation">}</span> 82 83<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 84<span class="token keyword">const</span> signature <span class="token operator">=</span> result<span class="token punctuation">.</span>signatures<span class="token operator">?.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=></span> item<span class="token punctuation">.</span>fileName <span class="token operator">===</span> fileName<span class="token punctuation">)</span><span class="token punctuation">;</span> 85 86<span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">.</span>status <span class="token operator">!==</span> <span class="token string">'OK'</span> <span class="token operator">||</span> <span class="token operator">!</span>signature<span class="token operator">?.</span>fileContent<span class="token punctuation">)</span> <span class="token punctuation">{</span> 87 <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'No signature returned for the requested file'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 88<span class="token punctuation">}</span> 89</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The HMAC is calculated over the exact JSON string sent as the request body. For batches, retain each original XML document and match each response by <code>fileName</code>.</p><h3 id="_3-insert-the-signature" tabindex="-1"><a class="header-anchor" href="#_3-insert-the-signature" aria-hidden="true">
89#</a> 3. Insert the signature</h3><div class="language-javascript line-numbers-mode" data-ext="js"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">insertSignature</span><span class="token punctuation">(</span><span class="token parameter">unsignedXml<span class="token punctuation">,</span> signatureBase64</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 90 <span class="token keyword">const</span> parser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DOMParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span> 91 <span class="token function">onError</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'Invalid XML'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> 92 <span class="token function">normalizeLineEndings</span><span class="token punctuation">(</span><span class="token parameter">text</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> text<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\\r\\n?</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'\\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> 93 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 94 <span class="token keyword">const</span> document <span class="token operator">=</span> parser<span class="token punctuation">.</span><span class="token function">parseFromString</span><span class="token punctuation">(</span>unsignedXml<span class="token punctuation">,</span> <span class="token string">'application/xml'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 95 <span class="token keyword">const</span> signatureXml <span class="token operator">=</span> Buffer<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>signatureBase64<span class="token punctuation">,</span> <span class="token string">'base64'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token string">'utf8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 96 <span class="token keyword">const</span> fragment <span class="token operator">=</span> parser<span class="token punctuation">.</span><span class="token function">parseFromString</span><span class="token punctuation">(</span>signatureXml<span class="token punctuation">,</span> <span class="token string">'application/xml'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 97 <span class="token keyword">const</span> signatureNode <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">importNode</span><span class="token punctuation">(</span>fragment<span class="token punctuation">.</span>documentElement<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 98 99 document<span class="token punctuation">.</span>documentElement<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>signatureNode<span class="token punctuation">)</span><span class="token punctuation">;</span> 100 101 <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">XMLSerializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 102 <span class="token punctuation">.</span><span class="token function">serializeToString</span><span class="token punctuation">(</span>document<span class="token punctuation">)</span> 103 <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">
103\\r</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'&#13;'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 104<span class="token punctuation">}</span> 105 106<span class="token keyword">const</span> signedXml <span class="token operator">=</span> <span class="token function">insertSignature</span><span class="token punctuation">(</span>unsignedXml<span class="token punctuation">,</span> signature<span class="token punctuation">.</span>fileContent<span class="token punctuation">)</span><span class="token punctuation">;</span> 107<span class="token keyword">await</span> <span class="token function">writeFile</span><span class="token punctuation">(</span><span class="token string">'document-signed.xml'</span><span class="token punctuation">,</span> signedXml<span class="token punctuation">,</span> <span class="token string">'utf8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 108</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Run with <code>node seal-xml.mjs</code> after setting the environment variables. This example appends the signature as the root's last child. To prepend it instead, replace the <code>appendChild</code> line with:</p><div class="language-javascript line-numbers-mode" data-ext="js"><pre class="language-javascript"><code>document<span class="token punctuation">.</span>documentElement<span class="token punctuation">.</span><span class="token function">insertBefore</span><span class="token punctuation">(</span>signatureNode<span class="token punctuation">,</span> document<span class="token punctuation">.</span>documentElement<span class="token punctuation">.</span>firstChild<span class="token punctuation">)</span><span class="token punctuation">;</span> 109</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>Choose the position permitted by your XML schema. If a signature container is required, it must already exist when you calculate the digest. Insert only the returned signature into that container; do not add surrounding whitespace or pretty-print the completed XML. The parser option above preserves XML 1.0 line-ending behavior. The serialization step escapes carriage returns as <code>&#13;</code> so character references in the original XML remain intact when the signed document is parsed again. Without this escape, a literal carriage return is normalized to a line feed on parsing, changing the document digest and invalidating the signature.</p><h2 id="validate-the-completed-xml" tabindex="-1"><a class="header-anchor" href="#validate-the-completed-xml" aria-hidden="true">#</a> Validate the completed XML</h2>`,15)),s("p",null,[n[14]||(n[14]=a("The example prepares the digest and inserts the signature. After insertion, validate the signature in the ",-1)),n[15]||(n[15]=s("strong",null,"complete signed XML document",-1)),n[16]||(n[16]=a(" using a validator that supports XAdES Baseline-LT, such as the European Commission's ",-1)),s("a",g,[n[13]||(n[13]=a("Digital Signature Service (DSS)",-1)),t(e)]),n[17]||(n[17]=a(" or another compatible signature validation tool or service.",-1))]),n[23]||(n[23]=s("p",null,"Validation should check document-reference integrity, the cryptographic signature, certificate trust and revocation status, the signature timestamp, and LT validation material under your chosen validation policy. Validating only the returned fragment cannot establish that the original XML matches the signed digest. eID E
109asy cannot verify that match because it receives only the digest.",-1)),n[24]||(n[24]=s("p",null,"If your document format requires an XML schema, also validate the completed XML against that schema. Schema validation checks document structure; it does not replace signature validation.",-1)),n[25]||(n[25]=s("p",null,"If document-reference validation fails, check the canonicalization mode, that you hashed the whole document rather than raw bytes, and that insertion preserved the original XML content and whitespace.",-1))])}const f=l(d,[["render",v],["__file","direct-e-sealing-xades-reference-digest-request.html.vue"]]);export{f as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.