Create an enveloping signature using a DSA key

Use this example to digitally sign an XML document with a DSA key, producing an enveloping signature that guarantees the document has not been tampered with.

An enveloping signature wraps the signed content inside the Signature element, keeping the data and signature together in a single output file. This example uses the DSA-SHA256 algorithm, which is the recommended algorithm for DSA digital signatures.

You can use the sample content provided in XML document (unsigned) for the purpose of testing the code. Copy the content to a file named "MyDocument.xml" in a directory where you test the sample code.

The sample code signs the XML document with a DSA private key named DSAKey.pem. Before running the example, generate the key with OpenSSL and copy it to the directory where you will run the sample code.

  1. Generate the DSA parameters:
    openssl dsaparam -out DSAparam.pem 2048
    The value 2048 specifies the key size in bits.
  2. Generate the private key and save it to DSAKey.pem:
    openssl gendsa -out DSAKey.pem DSAparam.pem

All keys or certificates in PEM or DER format were created with the OpenSSL tool. For information on how the OpenSSL tool works, refer to the openssl (external link) documentation.

Copy DSAKey.pem to the directory where you will run the sample code.

IMPORT xml

MAIN
  DEFINE doc xml.DomDocument
  DEFINE sig xml.Signature
  DEFINE key xml.CryptoKey
  DEFINE index INTEGER
  DEFINE objInd INTEGER
  # Create DomDocument object
  LET doc = xml.DomDocument.Create()
  # Notice that whitespaces are significant in cryptography, 
  # therefore it is recommended to remove unnecessary ones 
  CALL doc.setFeature("whitespace-in-element-content",FALSE)
  TRY
    # Load document to be signed
    CALL doc.load("MyDocument.xml")
    # Create DSA key and load it from file
    LET key = xml.CryptoKey.Create(
      "http://www.w3.org/2009/xmldsig11#dsa-sha256")
    CALL key.loadPEM("DSAKey.pem")
    # Create signature object with the key to use
    LET sig = xml.Signature.Create()
    CALL sig.setKey(key)
    # Create an object inside the signature to envelop the root node
    LET objInd = sig.createObject()
    # Set the object id to get a reference
    CALL sig.setObjectId(objInd,"data")
    # Copy the enveloping node from the document
    CALL sig.appendObjectData(objInd,doc.getDocumentElement())
    # Set the reference to be signed on the object node.
    # In our case, the object node with attribute 'data'
    LET index = sig.createReference("#data",
      "http://www.w3.org/2001/04/xmlenc#sha256")
    # Set canonicalization method on the enveloping object to be signed.
    CALL sig.appendReferenceTransformation(index,
      "http://www.w3.org/2001/10/xml-exc-c14n#")
    # Compute enveloping signature
    CALL sig.compute(NULL)
    # Retrieve signature document
    LET doc=sig.getDocument()
    # Save signature on disk
    CALL doc.setFeature("format-pretty-print",TRUE)
    CALL doc.save("MyDocumentEnvelopingSignature.xml")
  CATCH
    DISPLAY "Unable to create an enveloping signature :",status
  END TRY
END MAIN

For an example of the output produced by this code, see XML document (signed with DSA key).