Back to Contents


The Signature class

Summary

See also: The Genero Web Services XML Library


Syntax

The Signature class provides methods to create detached, enveloped or enveloping XML signatures of one or more references of XML documents or document fragments, and to determine whether a signed referenced document has been modified afterwards. It follows the XML-Signature specifications.

The status is set to zero after a successful method call.

Syntax

xml.Signature
 

Methods


Creation methods

Class Methods
Name Description
xml.Signature.Create()
   RETURNING xml.Signature
Constructor of a blank Signature object.
Returns a Signature object or NULL.

Throws an exception in case of errors, and updates status with an error code.

xml.Signature.CreateFromNode(
  sign xml.DomNode)
   RETURNING xml.Signature
Constructor of a new Signature object from a XML Signature node,
according to the XML-Signature specification.
Returns a Signature object or NULL.

The node must be an ELEMENT node with Signature as the local name, and belonging to the XML-Signature namespace http://www.w3.org/2000/09/xmldsig#, as defined here.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Key and certificate methods

Object Methods
Name Description
setKey(
  key xml.CryptoKey)
Defines the key used for signing or validation.

Only RSA, DSA of HMAC keys intended for SIGNATURE are allowed.

During the computation of the signature, some key information can be added according to the feature set on that CryptoKey object. If no features are set, nothing is added. See XML Signature concepts for more details.

Throws an exception in case of errors, and updates status with an error code.

setCertificate(
  cert xml.CryptoX509)
Defines the X509 certificate to be added to the Signature object when signing a document. If NULL, no certificate is added.

During the computation of the signature, some certificate information can be added according to the feature set on that CryptoX509 object. If no features are set, the complete X509 certificate is automatically added.

During the verification of a signature the certificate set with the  setCertificate method isn't used. See XML Signature concepts for more details.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Modifier method

Object Methods
Name Description
setCanonicalization(
  url STRING)
Sets the canonicalization method to use for the signature, where url is one of the four canonicalization identifier.
The default value is the c14n method.

Note: Windows .NET default c14n canonicalization method is not compatible with the w3c standard, therefore it is recommended to use the exc-c14n method when interoperating with a Windows system.

Throws an exception in case of errors, and updates status with an error code.

setID(
  id STRING)
Sets an ID value for the signature.
Throws an exception in case of errors, and updates status with an error code.

Back to the top


Access methods

Object Methods
Name Description
getType()
   RETURNING STRING
Returns a string with the type of the Signature object.

The string can be Detached, Enveloped, Enveloping or Invalid according to the XML-Signature specification.

Throws an exception in case of errors, and updates status with an error code.

getDocument()
   RETURNING xml.DomDocument
Returns a new DomDocument object representing the signature in XML.

If the type of the signature is enveloped, it's up to the user to add it at the right place in the XML document it is intended to sign.

Throws an exception in case of errors, and updates status with an error code.

getCanonicalization()
   RETURNING STRING
Returns one of the four canonicalization identifier of the signature.

Throws an exception in case of errors, and updates status with an error code.

getID()
   RETURNING STRING
Returns the ID value of the signature.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Reference modifier methods

Object Methods
Name Description
createReference(
  uri STRING,
  digest STRING)
   RETURNING INTEGER
Creates a new reference that will be signed with the compute() method, where uri represents the data to be signed, and digest a URL as identifier for the hash algorithm.

The returned value represents the index for any further manipulation of this reference.

The uri can be:

  • an absolute url such as http://, https://, tcp://, tcps://, file:/// and alias:// (see FGLPROFILE Configuration for more details about URL mapping with aliases), and where the data can be a XML document or any kind of data such as images or html pages.
  • NULL to sign the whole document, but only one NULL is allowed in the entire signature.
  • A fragment like #tobesigned. Note that a DOM node fragment is identified via the value of an attribute of type ID such as xml:id or any attribute whose type was changed to ID with setIdAttribute() or setIdAttributeNS().

Throws an exception in case of errors, and updates status with an error code.

setReferenceID(
  ind INTEGER,
  value STRING)
Sets an ID value for the signature reference of index ind.

Throws an exception in case of errors, and updates status with an error code.

appendReferenceTransformation(
  ind INTEGER,
  trans STRING,
  ...)
Appends a transformation related to the reference of index ind, and is executed before any computation; where trans represents an URL as identifier of the transformation algorithm.

A transformation modifies the reference URI before signing or validating it. Several transformations are executed one after another, and only once the last transformation was applied, is the reference really signed or verified.

Depending on the transformation identifier, additional parameters are necessary.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Reference access methods

Object Methods
Name Description
getReferenceCount()
   RETURNING INTEGER
Returns the number of references in this Signature object.

Throws an exception in case of errors, and updates status with an error code.

getReferenceURI(
  ind INTEGER)
   RETURNING STRING
Returns the URI of the reference of index ind in this Signature object.

Throws an exception in case of errors, and updates status with an error code.

getReferenceDigest(
  ind INTEGER)
   RETURNING STRING
Returns the digest algorithm identifier of the reference of index ind in this Signature object.

Throws an exception in case of errors, and updates status with an error code.

getReferenceID(
  ind INTEGER)
   RETURNING STRING
Returns the ID value of the reference of index ind in this Signature object, or NULL if there is none.

Throws an exception in case of errors, and updates status with an error code.

getReferenceTransformationCount(
  ind INTEGER),
   RETURNING INTEGER
Returns the number of transformation related to the reference of index ind.

Throws an exception in case of errors, and updates status with an error code.

getReferenceTransformation(
  ind INTEGER)
  pos INTEGER)
   RETURNING STRING
Returns the transformation identifier related to the reference of index ind, and at position pos in the list of transformation.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Object modifier methods

Object Methods
Name Description
createObject()
   RETURNING INTEGER
Creates a new object that will embed additional XML nodes.
The returned value represents the index for any further manipulation of this signature object.

Note: An object is enveloping additional XML nodes, but is not necessarily signed unless there is a reference on it.

Throws an exception in case of errors, and updates status with an error code.

setObjectID(
  ind INTEGER,
  value STRING)
Sets an ID value for the signature object of index ind.

Throws an exception in case of errors, and updates status with an error code.

appendObjectData(
  ind INTEGER,
  node xml.DomNode)
Appends a copy of a XML node node to the signature object of index ind.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Object access methods

Object Methods
Name Description
getObjectCount()
   RETURNING INTEGER
Returns the number of objects in this Signature object.

Throws an exception in case of errors, and updates status with an error code.

getObjectId(
  ind INTEGER)
   RETURNING STRING
Returns the ID value of the signature object of index ind in this Signature object.

Throws an exception in case of errors, and updates status with an error code.

Class Methods
Name Description
xml.Signature.RetrieveObjectDataListFromSignatureNode(
  sign xml.DomNode,
  ind INTEGER)
   RETURNING xml.DomNodeList
Returns a DomNodeList containing all embedded XML nodes related to the signature object of index ind in the XML Signature node node.

Throws an exception in case of errors, and updates status with an error code.

Back to the top


Signature computation and verification methods

Object Methods
Name Description
compute(
  doc xml.DomDocument)
Computes the signature of all references set in this Signature object.

If the signature type is:

  • Enveloping then doc must be NULL because all document fragment references are inside the Signature itself
  • Enveloped then doc must be the XML document where the signature must be added afterwards to get a valid enveloped signature
  • Detached then doc can be null if all references are absolute, otherwise it can be the XML document the fragment references are referencing
See XML Signature concepts for more details.
Also, see Windows .NET special recommendation

Throws an exception in case of errors, and updates status with an error code.

verify(
  doc xml.DomDocument)
   RETURNING INTEGER
Verifies whether all references in this Signature object haven't changed, and returns TRUE if valid, FALSE otherwise. If the signature type is:
  • Enveloping then doc must be NULL because all document fragment references are inside the Signature itself,
  • Enveloped then doc must be the XML document where the signature was enveloped,
  • Detached then doc can be null if all references are absolute, otherwise it can be the XML document the fragment references are referencing.
See XML Signature concepts for more details.

By default, the validation process uses the CryptoKey set with setKey() to verify the signature. However, if the signature contains a X509 certificate or a X509 retrieval method, it uses the list of trusted certificate, or if the signature contains a RSA or DSA retrieval method, it uses the RSA or DSA public key automatically loaded.

Note: See Windows .NET special recommendation

Throws an exception in case of errors, and updates status with an error code.

Back to the top


XML Signature concepts

The purpose of a signature is to verify the integrity of a XML document, that it was not altered, and that it still contains the same data as when it was created. The following points describe the different ways to achieve that.

Sign and verify with a common shared HMAC key

Sign with the originator private RSA or DSA key, and verify with the originator public RSA or DSA key

Sign with the originator private RSA or DSA key, and verify with a RSA or DSA retrieval method

Sign with the originator private RSA or DSA key, and verify with the originator X509 certificate associated to the private RSA or DSA key

Sign with the originator private RSA or DSA key, and verify with trusted X509 certificates

Sign with the originator private RSA or DSA key, and verify with a X509 certificate retrieval method and trusted X509 certificates

Sign with a named key and verify using the keystore

Back to the top


Digest identifier

Identifier Description
http://www.w3.org/2000/09/xmldsig#sha1
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a SHA algorithm of 160 bits.
Note: It is the only digest algorithm recommended by the W3C.
http://www.w3.org/2001/04/xmlenc#sha512
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a SHA algorithm of 512 bits.
http://www.w3.org/2001/04/xmldsig-more#sha384
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a SHA algorithm of 384 bits.
http://www.w3.org/2001/04/xmlenc#sha256
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a SHA algorithm of 256 bits.
http://www.w3.org/2001/04/xmldsig-more#sha224
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a SHA algorithm of 224 bits.
http://www.w3.org/2001/04/xmldsig-more#md5
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a MD5 algorithm.
http://www.w3.org/2001/04/xmlenc#ripemd160
(See
specification for details)
Computes the digest of the reference set with createReference(), by applying a hash operation using a RIPEMD algorithm.

Back to the top


Transformation identifier

Identifier Description Additional parameters
http://www.w3.org/2000/09/xmldsig#base64
(See specification for details)
Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
the raw data associated to a BASE64 encoded form.

This is intended to sign the raw data associated with the BASE64 encoded content of an element.

See specification for details.
No
http://www.w3.org/TR/2001/REC-xml-c14n-20010315
(See specification for details)
Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
a canonicalized XML document without any XML comments.

This is intended to transform two equivalent XML documents into a standardized XML representation in order to obtain the same hash value.

For instance: the following two XML nodes are equivalent but would produce different hash values if not canonicalized.
  • <tag Attr1="hello" Attr2="world"/>
  • <tag    Attr2="world"   Attr1="hello"   />


  • See specification for details.
    No
    http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments
    (See specification for details)
    Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
    a canonicalized XML document keeping all XML comments.

    This is intended to transform two equivalent XML documents into a standardized XML representation in order to obtain the same hash value.

    For instance:  the following two XML nodes are equivalent but would produce different hash values if not canonicalized.
  • <tag Attr1="hello" Attr2="world"/>
  • <tag    Attr2="world"   Attr1="hello"   />


  • See specification for details.
    No
    http://www.w3.org/2001/10/xml-exc-c14n#
    (See specification for details)
    Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
    a canonicalized XML document without any XML comments, and removing all unused namespaces declaration.

    This is intended to transform two equivalent XML documents into a standardized XML representation in order to obtain the same hash value.

    For instance:  the following two XML nodes are equivalent but would produce different hash values if not canonicalized.
  • <tag Attr1="hello" Attr2="world"/>
  • <tag    Attr2="world"   Attr1="hello"   />


  • See specification for details.
    No
    http://www.w3.org/2001/10/xml-exc-c14n#WithComments
    (See specification for details)
    Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
    a canonicalized XML document keeping all XML comments, and removing all unused namespaces declaration.

    This is intended to transform two equivalent XML documents into a standardized XML representation in order to obtain the same hash value.

    For instance:  following two XML nodes are equivalent but would produce different hash values if not canonicalized.
  • <tag Attr1="hello" Attr2="world"/>
  • <tag    Attr2="world"   Attr1="hello"   />


  • See specification for details.
    No
    http://www.w3.org/2000/09/xmldsig#enveloped-signature
    (See specification for details)
    Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
    the same XML document or fragment, but without the Signature node.

    This is intended to create enveloped signatures where the <dsig:Signature> node is inside the document, but without taking it into account during signature computation or verification.

    See specification for details.
    No
    http://www.w3.org/TR/1999/REC-xpath-19991116
    (See specification for details)
    Transforms the output from the previous transformation (or the reference if there is no previous transformation), into
    a XML document according to a XPath filtering expression applied to each node of the input document,
    where the expression represents a predicate to the XPath expression (//. | //@* | //namespace::*).
    In other words: (//. | //@* | //namespace::*)[expr]

    This is intended to identify the nodes to be signed using a XPath expression instead of an attribute of type ID.

    For instance, the following samples output only the MyCode node of the input document:
    CALL s.appendReferenceTransformation(
              i, "http://www.w3.org/TR/1999/REC-xpath-19991116",
              "ancestor-or-self::MyCode",
              NULL)
    CALL s.appendReferenceTransformation(
              i, "http://www.w3.org/TR/1999/REC-xpath-19991116",
              "ancestor-or-self::p:MyCode",
              "p","http://www.tempuri.org")

    See specification for details.

     
    XPath expression,
    followed by NULL
    or a list of prefix,namespace
    matching the XPath expression.
    http://www.w3.org/2002/06/xmldsig-filter2
    (See specification for details)
    Transforms the output from the previous transformation (or the reference if there is no previous transformation), into a XML document according to a XPath filtering 2.0 expression applied to the entire document at once.

    This is intended to identify the nodes to be signed using a XPath expression instead of an attribute of type ID, and to perform fast and more complex operations such as intersect, subtract or union.

    For instance, following samples output the entire document without the MyCode node child of the MyElement root node:
    CALL s.appendReferenceTransformation(
              i, "http://www.w3.org/2002/06/xmldsig-filter2",
              "subtract", "/MyElement/MyCode")
    CALL s.appendReferenceTransformation(
              i, "http://www.w3.org/2002/06/xmldsig-filter2",
              "subtract", "/p1:MyElement/p2:MyCode",
              "p2","http://www.tempuri.org/ns2",
              "p1","http://www.tempuri.org/ns1")
    
    See specification for details.
    XPathFilter2.0 type (intersect,subtract or union),
    followed by the XPath expression,
    followed by NULL
    or a list of prefix,namespace
    matching the XPath expression.

    Back to the top


    Examples

    Example 1 : Create a detached signature using a HMAC key

    01 IMPORT xml
    02
    03 MAIN
    04  DEFINE doc xml.DomDocument
    05   DEFINE root xml.DomNode
    06   DEFINE sig xml.Signature
    07   DEFINE key xml.CryptoKey
    08   DEFINE index INTEGER
    09   # Create DomDocument object
    10   LET doc = xml.DomDocument.Create()
    11   # Notice that whitespaces are significant in crytography,
    12   # therefore it is recommended that you remove unnecessary ones
    13   CALL doc.setFeature("whitespace-in-element-content",FALSE)
    14   TRY
    15    # Load document to be signed
    16     CALL doc.load("MyDocument.xml")
    17     # Create HMAC key
    18     LET key = xml.CryptoKey.Create("http://www.w3.org/2000/09/xmldsig#hmac-sha1")
    19     CALL key.setKey("secretpassword")
    20     # Create signature object with the key to use
    21     LET sig = xml.Signature.Create()
    22     CALL sig.setKey(key)
    23     # Set XML node to be signed. In our case, the node with attribute 'xml:id="code"'
    24     LET index = sig.createReference("#code","http://www.w3.org/2000/09/xmldsig#sha1")
    25     # Set canonicalization method on the XML fragment to be signed.
    26     CALL sig.appendReferenceTransformation(index,"http://www.w3.org/2001/10/xml-exc-c14n#")
    27     # Compute detached signature
    28     CALL sig.compute(doc)
    29     # Retrieve signature document
    30     LET doc=sig.getDocument()
    31     # Save signature on disk
    32     CALL doc.setFeature("format-pretty-print",TRUE)
    33     CALL doc.save("MyDocumentDetachedSignature.xml")
    34   CATCH
    35     DISPLAY "Unable to create a detached signature :",STATUS
    36   END TRY
    37 END MAIN

    Example 2 : Verify a detached signature using a HMAC key

    01 IMPORT xml
    02
    03 MAIN
    04   DEFINE doc xml.DomDocument
    05   DEFINE node xml.DomNode
    06   DEFINE sig xml.Signature
    07   DEFINE key xml.CryptoKey
    08   # Create DomDocument object
    09   LET doc = xml.DomDocument.Create()
    10   # Notice that whitespaces are significants in crytography,
    11   # therefore it is recommended to remove unnecessary ones
    12   CALL doc.setFeature("whitespace-in-element-content",FALSE)
    13   TRY
    14     # Load Signature into a DomDocument object
    15     CALL doc.load("MyDocumentDetachedSignature.xml")
    16     # Create signature object from DomDocument root node
    17     LET sig = xml.Signature.CreateFromNode(doc.getDocumentElement())
    18     # Create HMAC key and assign it to the signature object
    19     LET key = xml.CryptoKey.Create("http://www.w3.org/2000/09/xmldsig#hmac-sha1")
    20     CALL key.setKey("secretpassword")
    21     CALL sig.setKey(key)
    22     # Load original XML document into a DomDocument object
    23     CALL doc.load("MyDocument.xml")
    24     # Verify detached signature validity of original document
    25     LET isVerified = sig.verify(doc)
    26     # Notice that if something has been modified in the node with attribute 'xml:id="code"' of the original XML document,
    27     # the program will display "FAILED".
    28     IF isVerified THEN
    29       DISPLAY "Signature OK"
    30     ELSE
    31       DISPLAY "Signature FAILED"
    32     END IF
    33   CATCH
    34     DISPLAY "Unable to verify the detached signature :",STATUS
    35   END TRY
    36 END MAIN

    Example 3 : Create an enveloping signature using a DSA key

    01 IMPORT xml
    02
    03 MAIN
    04   DEFINE doc xml.DomDocument
    05   DEFINE root xml.DomNode
    06   DEFINE sig xml.Signature
    07   DEFINE key xml.CryptoKey
    08   DEFINE index INTEGER
    09   DEFINE objInd INTEGER
    10   # Create DomDocument object
    11   LET doc = xml.DomDocument.Create()
    12   # Notice that whitespaces are significants in crytography,
    13   # therefore it is recommended to remove unnecessary ones
    14   CALL doc.setFeature("whitespace-in-element-content",FALSE)
    15   TRY
    16     # Load document to be signed
    17     CALL doc.load("MyDocument.xml")
    18     # Create DSA key and load it from file
    19     LET key = xml.CryptoKey.Create("http://www.w3.org/2000/09/xmldsig#dsa-sha1")
    20     CALL key.loadPEM("DSAKey.pem")
    21     # Create signature object with the key to use
    22     LET sig = xml.Signature.Create()
    23     CALL sig.setKey(key)
    24     # Create an object inside the signature to envelop the root node
    25     LET objInd = sig.createObject()
    26     # Set the object id to get a reference
    27     CALL sig.setObjectId(objInd,"data")
    28     # Copy the enveloping node from the document
    29     CALL sig.appendObjectData(objInd,doc.getDocumentElement())
    30     # Set the reference to be signed on the object node. In our case, the object node with attribute 'data'
    31     LET index = sig.createReference("#data","http://www.w3.org/2000/09/xmldsig#sha1")
    32     # Set canonicalization method on the enveloping object to be signed.
    33     CALL sig.appendReferenceTransformation(index,"http://www.w3.org/2001/10/xml-exc-c14n#")
    34     # Compute enveloping signature
    35     CALL sig.compute(NULL)
    36     # Retrieve signature document
    37     LET doc=sig.getDocument()
    38     # Save signature on disk
    39     CALL doc.setFeature("format-pretty-print",TRUE)
    40     CALL doc.save("MyDocumentEnvelopingSignature.xml")
    41   CATCH
    42     DISPLAY "Unable to create an enveloping signature :",STATUS
    43   END TRY
    44 END MAIN

    Example 4 : Verify an enveloping signature using a X509 certificate

    01 IMPORT xml
    02
    03 MAIN
    04   DEFINE doc xml.DomDocument
    05   DEFINE node xml.DomNode
    06   DEFINE sig xml.Signature
    07   DEFINE cert xml.CryptoX509
    08   DEFINE pub xml.CryptoKey
    09   # Create DomDocument object
    10   LET doc = xml.DomDocument.Create()
    11   # Notice that whitespaces are significants in crytography,
    12   # therefore it is recommended to remove unnecessary ones
    13   CALL doc.setFeature("whitespace-in-element-content",FALSE)
    14   TRY
    15     # Load Signature into a DomDocument object
    16     CALL doc.load("MyDocumentEnvelopingSignature.xml")
    17     # Create signature object from DomDocument root node
    18     LET sig = xml.Signature.CreateFromNode(doc.getDocumentElement())
    19     # Create X509 certificate
    20     LET cert = xml.CryptoX509.Create()
    21     CALL cert.loadPEM("DSACertificate.crt")
    22     # Create public key from that X509 certificate
    23     LET pub = cert.createPublicKey("http://www.w3.org/2000/09/xmldsig#dsa-sha1")
    24     # Assign it to the signature
    25     CALL sig.setKey(pub)
    26     # Verify enveloping signature validity
    27     LET isVerified = sig.verify(NULL)
    28     # Notice that if something has been modified in the signature
    29     # or if the certificate isn't associated to the private DSA key of exemple 3,
    30     # the program will display "FAILED".
    31     IF isVerified THEN
    32       DISPLAY "Signature OK"
    33     ELSE
    34       DISPLAY "Signature FAILED"
    35     END IF
    36   CATCH
    37     DISPLAY "Unable to verify the enveloping signature :",STATUS
    38   END TRY
    39 END MAIN

    Example 5 : Create an enveloped signature using a RSA key

    01 IMPORT xml
    02
    03 MAIN
    04   DEFINE doc xml.DomDocument
    05   DEFINE doc2 xml.DomDocument
    06   DEFINE root xml.DomNode
    07   DEFINE node xml.DomNode
    08   DEFINE signNode xml.DomNode
    09   DEFINE sig xml.Signature
    10   DEFINE key xml.CryptoKey
    11   DEFINE index INTEGER
    12   # Create DomDocument object
    13   LET doc = xml.DomDocument.Create()
    14   # Notice that whitespaces are significants in crytography,
    15   # therefore it is recommended to remove unnecessary ones
    16   CALL doc.setFeature("whitespace-in-element-content",FALSE)
    17   TRY
    18     # Load document to be signed
    19     CALL doc.load("MyDocument.xml")
    20     # Create rsa key
    21     LET key = xml.CryptoKey.Create("http://www.w3.org/2000/09/xmldsig#rsa-sha1")
    22     CALL key.loadPEM("RSAKey.pem")
    23     # Create signature object with the key to use
    24     LET sig = xml.Signature.Create()
    25     CALL sig.setKey(key)
    26     # Set XML node to be signed. In our case, the node with attribute 'xml:id="code"'
    27     LET index = sig.createReference("#code","http://www.w3.org/2000/09/xmldsig#sha1")
    28     # Add enveloped method to not take the XML signature node into account when computing the entire document.
    29     CALL sig.appendReferenceTransformation(index,"http://www.w3.org/2000/09/xmldsig#enveloped-signature")
    30     # Set canonicalization method on the XML fragment to be signed.
    31     CALL sig.appendReferenceTransformation(index,"http://www.w3.org/2001/10/xml-exc-c14n#")
    32     # Compute enveloped signature
    33     CALL sig.compute(doc)
    34     # Retrieve signature document
    35     LET doc2=sig.getDocument()
    36     # Append the signature node to the original document to get a valid enveloped signature
    37     # Notice that the enveloped signature can be added anywhere in the original document
    38     LET signNode = doc2.getDocumentElement() # Get Signature node
    39     LET node = doc.importNode(signNode,true) # Import it into the original document
    40     LET root = doc.getDocumentElement() # Retrieve the original document root node
    41     CALL root.appendChild(node) # Append the signature node as last child of the original document
    42     # Save document with enveloped signature back to disk
    43     CALL doc.setFeature("format-pretty-print",TRUE)
    44     CALL doc.save("MyDocumentEnvelopedSignature.xml")
    45   CATCH
    46     DISPLAY "Unable to create an enveloped signature :",STATUS
    47   END TRY
    48 END MAIN

    Example 6 : Verify an enveloped signature using a RSA key

    01 IMPORT xml
    02
    03 MAIN
    04   DEFINE doc xml.DomDocument
    05   DEFINE node xml.DomNode
    06   DEFINE sig xml.Signature
    07   DEFINE key xml.CryptoKey
    08   DEFINE list xml.DomNodeList
    09   # Create DomDocument object
    10   LET doc = xml.DomDocument.Create()
    11   # Notice that whitespaces are significants in crytography,
    12   # therefore it is recommended to remove unnecessary ones
    13   CALL doc.setFeature("whitespace-in-element-content",FALSE)
    14   TRY
    15     # Load original document with enveloped signature into a DomDocument object
    16     CALL doc.load("MyDocumentEnvelopedSignature.xml")
    17     # Because the signature can be anywhere in the original document, we must first retrieve it
    18     LET list = signature.getElementsByTagNameNS("Signature","http://www.w3.org/2000/09/xmldsig#")
    19     IF list.getCount() != 1 THEN
    20       DISPLAY "Unable to find one Signature node"
    21       EXIT PROGRAM (-1)
    22     ELSE
    23       LET node = list.getItem(1)
    24     END IF
    25     # Create RSA key
    26     LET key = xml.CryptoKey.Create("http://www.w3.org/2000/09/xmldsig#rsa-sha1")
    27     CALL key.loadPEM("RSAKey.pem")
    28     # Create signature object from DomNode object and set RSA key to use
    29     LET sig = xml.Signature.CreateFromNode(node)
    30     CALL sig.setKey(key)
    31     # Verify enveloped signature validity of original document
    32     LET isVerified = sig.verify(doc)
    33     # Notice that if something has been modified in the node with attribute 'xml:id="code"' of the original XML document with the enveloped signature,
    34     # the program will display "FAILED".
    35     IF isVerified THEN
    36       DISPLAY "Signature OK"
    37     ELSE
    38       DISPLAY "Signature FAILED"
    39     END IF
    40  CATCH
    41     DISPLAY "Unable to verify the enveloped signature :",STATUS
    42   END TRY
    43 END MAIN

    Important! All keys or certificates in PEM or DER format were created with the OpenSSL tool.

    Back to the top