Enveloped vs Enveloping vs Detached XML Signatures

XML Digital Signatures (XMLDSig) provide data integrity, authentication, and non-repudiation for digital assets. The XML standard defines three primary signature types based on the structural relationship between the <Signature> element and the data being signed: enveloped, enveloping, and detached. The fundamental difference lies in whether the signature is contained within the signed data, contains the signed data, or exists independently of it.

Enveloped Signatures

In an enveloped signature, the <Signature> element is nested inside the XML content that it signs. The signature is a child element of the target data’s root element.

Because the signature is placed inside the data being signed, calculating the cryptographic digest would create a circular dependency (signing the signature itself). To resolve this, enveloped signatures must use the standard enveloped-signature transform (a specific XPath filter), which strips out the <Signature> block before calculating the digest value.

Structural Example

<RootDocument id="doc1">
    <DataElement>Signed content goes here</DataElement>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:Reference URI="#doc1">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                </ds:Transforms>
                <!-- Digest and algorithms -->
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>...</ds:SignatureValue>
    </ds:Signature>
</RootDocument>

Enveloping Signatures

In an enveloping signature, the relationship is reversed: the <Signature> element is the outer container that encloses the signed data. The signed content is placed inside a <ds:Object> element, which is a child of the <Signature> element.

The <Reference> element inside the <SignedInfo> references the ID of the <ds:Object> containing the payload. Unlike enveloped signatures, no specialized exclusion transforms are needed because the signature metadata sits outside the signed payload.

Structural Example

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
        <ds:Reference URI="#payload1">
            <!-- Digest and algorithms -->
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>...</ds:SignatureValue>
    <ds:Object Id="payload1">
        <OriginalData>This entire payload is inside the signature</OriginalData>
    </ds:Object>
</ds:Signature>

Detached Signatures

In a detached signature, the <Signature> element and the signed data are completely independent of each other. They do not have a parent-child relationship.

Detached signatures occur in two common variations:

  1. Internal Detached: The signature and the signed data exist within the same XML document as sibling elements under a common root.
  2. External Detached: The signature and the signed data exist in completely separate files or locations. The signed data can be an external XML file, an image, a PDF, or any binary resource accessed via a URI.

Structural Example (Internal Detached)

<Container>
    <DataElement id="data1">Data signed independently</DataElement>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:Reference URI="#data1">
                <!-- Digest and algorithms -->
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>...</ds:SignatureValue>
    </ds:Signature>
</Container>

Structural Example (External Detached)

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
        <ds:Reference URI="https://example.com/documents/contract.pdf">
            <!-- Digest and algorithms -->
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>...</ds:SignatureValue>
</ds:Signature>

Structural Comparison Summary

Signature Type Signature Position Signed Data Position Reference Target
Enveloped Child element Parent/Ancestor element Root or parent node ID
Enveloping Root/Container Inside <ds:Object> child <ds:Object> ID
Detached Separate node or file Sibling node or external resource Node ID or External URI