CryptoSys Home > SC14N > Signing an XML-DSIG document using SC14N

Signing an XML-DSIG document using SC14N

This page is a more detailed explanation of the function MakeSignedXml() in TestSc14nPki.cs and TestSc14nPKI.c and the Python function make_signed_xml() in The code has been tailored for a specific set of conditions, but could easily be adapted for other situations.

The code does all of the substitution operations in memory, starting with a base file, and finally writes the completed document to a file. You could alternatively do these operations using the command line and a text editor.

Base document: enveloped signature with Latin-1 encoded original

The base document (olamundo-base.xml) with %% parameters to be completed.

 1 <?xml version="1.0" encoding="ISO-8859-1"?>
 2 <Envelope xmlns="">
 3   <Body>
 4     Olá mundo
 5   </Body>
 6   <Signature xmlns="">
 7     <SignedInfo>
 8       <CanonicalizationMethod Algorithm="" />
 9       <SignatureMethod Algorithm="" />
10       <Reference URI="">
11         <Transforms>
12           <Transform Algorithm="" />
13         </Transforms>
14         <DigestMethod Algorithm="" />
15         <DigestValue>%digval%</DigestValue>
16       </Reference>
17     </SignedInfo>
18     <SignatureValue>%sigval%</SignatureValue>
19     <KeyInfo>
20       <KeyValue>%keyval%</KeyValue>
21     </KeyInfo>
22   </Signature>
23 </Envelope>



  1. Compute the digest value of the document excluding the <Signature> element. We use the default SHA-1 algorithm here to match the DigestMethod algorithm we wrote in line 14.
    > sc14n -d -x Signature olamundo-base.xml
    In C#:
    digval = C14n.ToDigest(baseFile, "Signature", Tran.ExcludeByTag, DigAlg.Sha1);
  2. Substitute this value for the %digval% parameter in line 15.
     7     <SignedInfo>
     8       <CanonicalizationMethod Algorithm="" />
     9       <SignatureMethod Algorithm="" />
    10       <Reference URI="">
    11         <Transforms>
    12           <Transform Algorithm="" />
    13         </Transforms>
    14         <DigestMethod Algorithm="" />
    15         <DigestValue>UWuYTYug10J1k5hKfonxthgrAR8=</DigestValue>
    16       </Reference>
    17     </SignedInfo>
  3. Compute the signature value over the c14n transformation of the now-completed SignedInfo element.
    1. Compute the SHA-1 digest of the updated SignedInfo element. We use SHA-1 here to match the rsa-sha1 SignatureMethod algorithm we wrote in line 9.
      > sc14n -d -s SignedInfo olamundo-inter.xml
      In C#, where s contains the updated <SignedInfo> element:
      digval_si = C14n.ToDigest(System.Text.Encoding.UTF8.GetBytes(s), DigAlg.Sha1);
    2. Use a PKI function to compute the base64-encoded rsa-sha1 signature value using this digest value together with the signer's private RSA key.
      Using Python:
      >>> sigval = pki.Sig.sign_data(s, myprikey, mypassword, pki.Sig.Alg.RSA_SHA1)
      Using C#:
      string sigval = Pki.Sig.SignDigest(Pki.Cnv.FromBase64(digval), priKey, password, Pki.SigAlgorithm.Rsa_Sha1);
  4. Substitute this value for the %sigval% parameter in line 18.
  5. Use a PKI function to extract the <RSAKeyValue> value from the signer's public certificate (or RSA private key), then substitute for the %keyval% parameter in line 20. The signed document is now complete.

    In practice, also, you'd normally be using the same key info, so you could just hard code the details in your base file (note that white space and newlines inside the <KeyInfo> element do not affect the signature).


    We use <RSAKeyValue> in our examples because we want to test them on Alexey's XML validator site. In practice, you'd probably be using an <X509Certificate> element instead, perhaps with an <X509IssuerSerial> and <X509SubjectName>. The following contains the same public key information as above, but inside an X509 certificate.


The final signed document


The files referenced on this page

The zip contains the base, intermediate and final versions of olamundo.xml, plus the private key and certificate used to do the signing.

The source code

Included in the distribution download or the Python download.


For further information or to comment on this page, please send us a message.

This page last updated 9 June 2020.