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 test_sc14n_pki.py. 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="http://example.org/envelope">
 3   <Body>
 4     Olá mundo
 5   </Body>
 6   <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
 7     <SignedInfo>
 8       <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
 9       <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
10       <Reference URI="">
11         <Transforms>
12           <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
13         </Transforms>
14         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
15         <DigestValue>%digval%</DigestValue>
16       </Reference>
17     </SignedInfo>
18     <SignatureValue>%sigval%</SignatureValue>
19     <KeyInfo>
20       <KeyValue>%keyval%</KeyValue>
21     </KeyInfo>
22   </Signature>
23 </Envelope>

Preconditions

Procedure

  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
    UWuYTYug10J1k5hKfonxthgrAR8=
    
    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="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
     9       <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
    10       <Reference URI="">
    11         <Transforms>
    12           <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
    13         </Transforms>
    14         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
    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
      oloG0znWi2Jc1zg6kyNXiJlWpU4=
      
      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).

    <KeyInfo>    
      <KeyValue>
        <RSAKeyValue>
          <Modulus>4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8Zo
          bwfZsGCsvu40CWoT9fcFBZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18=</Modulus>
          <Exponent>AQAB</Exponent>
        </RSAKeyValue>
      </KeyValue>
    </KeyInfo>
    

    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.

    <KeyInfo>    
      <X509Data>
        <X509Certificate>
    	MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUFADAS
    	MRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1
    	OVowEzERMA8GA1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
    	AoGBAOCJczmN2PX16Id2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8
    	l+z6glEPMIC+sVCeRkTxLLvYMs/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Z
    	f8mB5vhs6odAcO+sbSx0ny36VTq5mXcCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAM
    	BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBTp4JAnrHgg
    	eprTTPJCN04irp44uzAdBgNVHQ4EFgQUd9K00bdMioqjzkWdzuw8oDrj/1AwHwYD
    	VR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADgYEA
    	PnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzPbrMcWakgqgWBqE4lradw
    	FHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2Tt0z3Sp0LF6DeK
    	tNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCI=
        </X509Certificate>
      </X509Data>
    </KeyInfo>
    

The final signed document

olamundo-signed.xml.

The files referenced on this page

The zip examples-base.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.

Contact

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

This page last updated 9 June 2020.