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.

getSignatureMethod()
   RETURNING STRING
Returns the algorithm method 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

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.

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.

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, 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/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, the 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 

Note: All keys or certificates in PEM or DER format were created with the OpenSSL tool.

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

Note: All keys or certificates in PEM or DER format were created with the OpenSSL tool.

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 

Note: All keys or certificates in PEM or DER format were created with the OpenSSL tool.

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 

Note: All keys or certificates in PEM or DER format were created with the OpenSSL tool.

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

Note: All keys or certificates in PEM or DER format were created with the OpenSSL tool.

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 

Note: All keys or certificates in PEM or DER format were created with the OpenSSL tool.

Back to the top