CryptoSys Home > SC14N > Exclusive C14N examples

Exclusive C14N examples


Using exclusive c14n to solve problems with re-enveloping

The following examples from section 2.2 of Exclusive XML Canonicalization, Version 1.0 show the difference between using inclusive and exclusive c14n to canonicalize the same element enveloped differently.

[Note there is a typo in the original document: xml:space="retain" should be xml:space="preserve".]

example1.xml

<n0:local xmlns:n0="foo:bar"
        xmlns:n3="ftp://example.org">
 <n1:elem2 xmlns:n1="http://example.net"
           xml:lang="en">
     <n3:stuff xmlns:n3="ftp://example.org"/>
 </n1:elem2>
</n0:local>

example2.xml

<n2:pdu xmlns:n1="http://example.com"
      xmlns:n2="http://foo.example"
      xml:lang="fr"
      xml:space="preserve">

 <n1:elem2 xmlns:n1="http://example.net"
           xml:lang="en">
     <n3:stuff xmlns:n3="ftp://example.org"/>
 </n1:elem2>
</n2:pdu>

The internal element <n1:elem2> is the same in both cases but the enveloping is different.

Transforming the element <n1:elem2> using inclusive c14n gives two different results, because of the different enveloping elements.
> sc14n -s n1:elem2 example1.xml
<n1:elem2 xmlns:n0="foo:bar" xmlns:n1="http://example.net" xmlns:n3="ftp://example.org" xml:lang="en">
         <n3:stuff></n3:stuff>
 </n1:elem2>
 
> sc14n --digest-value -s n1:elem2 example1.xml
RSTxYngjk7kroYxpMtbJP2g7Q3s=
 
> sc14n -s n1:elem2 example2.xml
<n1:elem2 xmlns:n1="http://example.net" xmlns:n2="http://foo.example" xml:lang="en" xml:space="preserve">
         <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
 </n1:elem2>
 
> sc14n --digest-value -s n1:elem2 example2.xml
x9seNaaK3lTVs9n2WIIrIgDDU1E=
However, using exclusive c14n gives identical results.
> sc14n --exclusive -s n1:elem2 example1.xml
<n1:elem2 xmlns:n1="http://example.net" xml:lang="en">
         <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
 </n1:elem2>
 
> sc14n -d --exclusive -s n1:elem2 example1.xml
qYwgpdgV1/b3PQ3aSpMx9wKGtqY=

> sc14n --exclusive -s n1:elem2 example2.xml
<n1:elem2 xmlns:n1="http://example.net" xml:lang="en">
         <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
 </n1:elem2>
 
> sc14n -d --exclusive -s n1:elem2 example2.xml
qYwgpdgV1/b3PQ3aSpMx9wKGtqY=

Example using SOAP with PrefixList

Consider the following XML document, shown prettified with line indents for clarity. The original file is here. This document is based on something sent to us a few years ago. It is a good example of using exclusive c14n with the InclusiveNamespaces PrefixList parameter, a list of namespace prefixes which should be handled as in inclusive c14n.

See below for comments and analysis. Note that the line numbers refer to the prettified document here not the original file.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header>
    <wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
	  ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" 
      wsu:Id="X509-9556B866A399B750FC14086322399999"> 
        MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1
        OVowEzERMA8GA1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCJczmN2PX16Id2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8
        l+z6glEPMIC+sVCeRkTxLLvYMs/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mXcCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAM
        BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQUd9K00bdMioqjzkWdzuw8oDrj/1AwHwYD
        VR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADgYEAPnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzPbrMcWakgqgWBqE4lradw
        FHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2Tt0z3Sp0LF6DeKtNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCI=
      </wsse:BinarySecurityToken>
      <ds:Signature Id="SIG-4" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <ec:InclusiveNamespaces PrefixList="SOAP-ENV" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
          <ds:Reference URI="#TS-3">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces PrefixList="wsse SOAP-ENV" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>a4cojI7ZDOI1lKvGD7OHNus7qy1DQgpqNdGZ/YEDJQo=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
        ZPAEqEVHH1WHNcEBvunK5YjyTi1RS1djiM0KI46H1lmESKJYX+c9+LOIuXo5Yyf6ysQwIIDlRlvbbzXSqzmXax1IQMc8xvgNVlOdf5F20NyPoylVTG8iJyBLrAniM7tpFEEfGLGLxKOajodxrO8xi87YnYWsIku0J4UYjP5lqbc=
        </ds:SignatureValue>
        <ds:KeyInfo Id="KI-9556B866A399B750FC14086322393075">
          <wsse:SecurityTokenReference wsu:Id="STR-9556B866A399B750FC14086322393076">
            <wsse:Reference URI="#X509-9556B866A399B750FC14086322399999" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
          </wsse:SecurityTokenReference>
          <ds:KeyValue>
            <ds:RSAKeyValue>
              <ds:Modulus>
              4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8
              ZobwfZsGCsvu40CWoT9fcFBZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18=
              </ds:Modulus>
              <ds:Exponent>AQAB</ds:Exponent>
            </ds:RSAKeyValue>
          </ds:KeyValue>
        </ds:KeyInfo>
      </ds:Signature>
      <wsu:Timestamp wsu:Id="TS-3">
        <wsu:Created>2018-11-17T14:43:59Z</wsu:Created>
        <wsu:Expires>2018-11-17T14:44:04Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ViewAccountSummary xmlns="http://viewaccountsummary.xyz.com">
      <ViewAccountSummaryParameters xmlns="">
        <UserDetails xmlns="http://viewaccountsummary.xyz.com">
          <UserId>9999</UserId>
          <AuthorizationId>XXXX</AuthorizationId>
        </UserDetails>
        <accountNumber xmlns="http://viewaccountsummary.xyz.com">9999999999999999999</accountNumber>
        <bankId xmlns="http://viewaccountsummary.xyz.com">999999999</bankId>
      </ViewAccountSummaryParameters>
    </ViewAccountSummary>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Comments on the above SOAP document

Despite its length and complexity, only one thing is signed in this document. That's the four-line <wsu:Timestamp> element with Id "TS-3" at lines 49-52. The reference to this is in lines 21-29, beginning with <ds:Reference URI="#TS-3">. Exclusive c14n is to be used for the transformation (line 23) but with the PrefixList set to wsse SOAP-ENV (line 24). So any element with prefix "wsse" or "SOAP-ENV" is to be treated as though it's being transformed using inclusive c14n.

Note also that the actual Signature is computed using a different PrefixList (line 18).

Given the original document, we compute the canonicalized transform and the SHA-256 digest value as follows. (We've added line wrapping to the sc14n output for readability.)

> sc14n --exclusive --prefix-list="wsse SOAP-ENV" -S "wsu:Id=TS-3" soap-ts3-signed-by-alice.xml
<wsu:Timestamp xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
	xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
	wsu:Id="TS-3">
<wsu:Created>2018-11-17T14:43:59Z</wsu:Created>
<wsu:Expires>2018-11-17T14:44:04Z</wsu:Expires>
</wsu:Timestamp>

> sc14n -d2 --exclusive --prefix-list="wsse SOAP-ENV" -S "wsu:Id=TS-3" soap-ts3-signed-by-alice.xml
a4cojI7ZDOI1lKvGD7OHNus7qy1DQgpqNdGZ/YEDJQo=

This digest value is inserted into the DigestValue element on line 28 (already done) and the signature is computed over the SignedInfo element (lines 16-30). The canonicalization method for the signature is exclusive c14n (line 17) with a PrefixList of SOAP-ENV (line 18). We can compute the SHA-256 digest of the c14n transformation of the SignedInfo as follows:

> sc14n -d2 --exclusive --prefix-list="SOAP-ENV" -s "ds:SignedInfo" soap-ts3-signed-by-alice.xml
VenfIoZjs3/LxtvQdQuHIizR3vKi7TViE1ZF7Ddnn8I=

To compute the signature value itself we need the private key of the signer. Here is Alice's encrypted private key AlicePrivRSASign.p8e (with password="password") and her matching X.509 certificate AliceRSASignByCarl.cer (note this matches the base64 data in <wsse:BinarySecurityToken>).

Using CryptoSys PKI Pro with Python and C#

Using our Python interface to CryptoSys PKI Pro, we obtain the required base64 signature value, using the rsa-sha256 signature algorithm over the digest value we computed above.

>>> from cryptosyspki import *
>>> sigval = Sig.sign_digest(Cnv.frombase64('VenfIoZjs3/LxtvQdQuHIizR3vKi7TViE1ZF7Ddnn8I='), 'AlicePrivRSASign.p8e', "password", Sig.Alg.RSA_SHA256, encoding=Sig.Encoding.BASE64)
>>>
>>> print sigval
ZPAEqEVHH1WHNcEBvunK5YjyTi1RS1djiM0KI46H1lmESKJYX+c9+LOIuXo5Yyf6ysQwIIDlRlvbbzXSqzmXax1IQMc8xvgNVlOdf5F20NyPoylVTG8iJyBLrAniM7tpFEEfGLGLxKOajodxrO8xi87YnYWsIku0J4UYjP5lqbc=
>>>
In C#:
using CryptoSysPKI;
string sigval = Sig.SignDigest(Cnv.FromBase64("VenfIoZjs3/LxtvQdQuHIizR3vKi7TViE1ZF7Ddnn8I="),
	"AlicePrivRSASign.p8e", "password", SigAlgorithm.Rsa_Sha256);

Insert this result into the <ds:SignatureValue> element (line 32) and the final document is ready.

Incidentally, to get the <ds:RSAKeyValue> element (lines 39-45) from Alice's X.509 certificate, we do the following in Python.

>>> keystr = Rsa.read_public_key('AliceRSASignByCarl.cer')
>>> Rsa.to_xmlstring(keystr, prefix="ds")
'<ds:RSAKeyValue>
<ds:Modulus>
  4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcFBZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18=
</ds:Modulus>
<ds:Exponent>AQAB</ds:Exponent>
</ds:RSAKeyValue>'
In C#:
string keystr = Rsa.ReadPublicKey("AliceRSASignByCarl.cer").ToString();
string rsaval = Rsa.ToXMLString(keystr, "ds", 0);

And to get the base64-encoded X.509 data for the <wsse:BinarySecurityToken> element (lines 8-13), do the following

>>> x509str = X509.read_string_from_file('AliceRSASignByCarl.cer')
>>> print x509str
MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCJczmN2PX16Id2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sVCeRkTxLLvYMs/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mXcCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQUd9K00bdMioqjzkWdzuw8oDrj/1AwHwYDVR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADgYEAPnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzPbrMcWakgqgWBqE4lradwFHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2Tt0z3Sp0LF6DeKtNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCI=
In C#:
string x509str = X509.ReadStringFromFile("AliceRSASignByCarl.cer");

Verify

You can verify that the above XML signed document is correct at the Online XML Digital Signature Verifer. Copy-and-paste the original Signed XML Document onto the web page and click on "Verify Signature". (Note that the <!DOCTYPE> element is required for the verifier site to cope with the Id reference).

New2022-03-20: See Troubleshooting problems on the 'Online XML Digital Signature Verifier' site

Download the docs

All the above documents in a zipped file (4.2 kB).

References

Contact

To comment on this page, please send us a message.

This page last updated 2 August 2023.