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.