Discuss this help topic in SecureBlackbox Forum

XML: Create enveloped signature

If the XML signature is used to sign some part or its containing document, then it is called an enveloped signature. The content of <ds:Signature> element must be excluded from the calculations of the data digest and signature value (that is, the content of <ds:DigestValue> and <ds:SignatureValue>). This can be achieved by enabling enveloped-signature transform (whose identifier is "http://www.w3.org/2000/09/xmldsig#enveloped-signature"), as shown in the following example.

Original document:


<Root>
<Data>Hello, World!</Data>
</Root>

Signed document:


<Root>
<Data>Hello, World!</Data>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    <ds:Reference URI="">
      <ds:Transforms>
        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
      </ds:Transforms>
      <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
      <ds:DigestValue>...</ds:DigestValue>
    </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue>...</ds:SignatureValue/>
  <ds:KeyInfo>...</ds:KeyInfo>
</ds:Signature>
</Root>

Code sample:

C#:


void Sign(TElXMLDOMDocument Doc, TElX509Certificate Cert)
{
  TElXMLSigner Signer = new TElXMLSigner(null);
  TElXMLKeyInfoX509Data X509Data = new TElXMLKeyInfoX509Data(false);
  try
  {
    Signer.SignatureType = SBXMLSec.Unit.xstEnveloped;
    Signer.CanonicalizationMethod = SBXMLDefs.Unit.xcmCanon;
    Signer.SignatureMethodType = SBXMLSec.Unit.xmtSig;
    Signer.SignatureMethod = SBXMLSec.Unit.xsmRSA_SHA1;

    TElXMLReference Ref = new TElXMLReference();
    Ref.DigestMethod = SBXMLSec.Unit.xdmSHA1;
    Ref.URI = "";
    Ref.URINode = Doc.DocumentElement;
    Ref.TransformChain.AddEnvelopedSignatureTransform();
    Signer.References.Add(Ref);

    X509Data.Certificate = Cert;
    Signer.KeyData = X509Data;

    Signer.UpdateReferencesDigest();
    Signer.GenerateSignature();

    Signer.SaveEnveloped(Doc.DocumentElement);
  }
  finally
  {
    Signer.Dispose();
    X509Data.Dispose();
  }
}
Delphi:

procedure Sign(Doc : TElXMLDOMDocument; Cert : TElX509Certificate);
var
  Signer: TElXMLSigner;
  X509Data: TElXMLKeyInfoX509Data;
  Ref: TElXMLReference;
begin
  Signer:= TElXMLSigner.Create(nil);
  X509Data := TElXMLKeyInfoX509Data.Create(false);
  try
    Signer.SignatureType := xstEnveloped;
    Signer.CanonicalizationMethod := xcmCanon;
    Signer.SignatureMethodType := xmtSig;
    Signer.SignatureMethod := xsmRSA_SHA1;

    Ref := TElXMLReference.Create;
    Ref.DigestMethod := xdmSHA1;
    Ref.URI := '';
    Ref.URINode := Doc.DocumentElement;
    Ref.TransformChain.AddEnvelopedSignatureTransform();
    Signer.References.Add(Ref);

    X509Data.Certificate := Cert;
    Signer.KeyData := X509Data;

    Signer.UpdateReferencesDigest;

    Signer.GenerateSignature;

    Signer.SaveEnveloped(Doc.DocumentElement);
  finally
    FreeAndNil(Signer);
    FreeAndNil(X509Data);
  end;
end;

The data referenced in the <ds:Signature> element and specified by the "URI=''" attribute of the <ds:Reference> descendant element is the entire Root element, including <ds:Signature> itself. The instruction <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> ensures that the <ds:Signature> element is excluded from the signature processing.

How To articles about XML signing (XMLDSig and XAdES)

Discuss this help topic in SecureBlackbox Forum