How to: Determine Which Parts of a SOAP Message Were Signed or Encrypted

WSE allows a SOAP message recipient to programmatically determine the portions of the SOAP message that were signed or encrypted. By default, if the SOAP message sender is using WSE, WSE encrypts the entire contents of the <Body> element and none of the SOAP headers. For digital signing, WSE signs the entire contents of the <Body> element, the <Timestamp> element of the Security header, and all addressing headers. However, the sender need not be using WSE, and even if they are, these default settings can be overridden. For details about overriding the default WSE settings, see Signing Custom SOAP Headers.

To determine which parts of a SOAP message were signed

  1. Create a custom policy assertion.

    For more details about creating custom policy assertions, see How to: Create a Custom Policy Assertion that Secures SOAP Messages.

  2. In the input SOAP filter for the client or the Web service that signs SOAP messages, override the ValidateMessageSecurity method.

    The following code example overrides the ValidateMessageSecurity method for the output SOAP filter.

    Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
    
    public override void  ValidateMessageSecurity(SoapEnvelope envelope, Security security)
    
  3. Iterate over the Elements collection of the security parameter for the SecureMessage method.

    The following code example iterates over the security parameter for a SOAP request.

    Dim element As ISecurityElement
    For Each element In security.Elements
    
    foreach (ISecurityElement element in security.Elements)
    
  4. Determine whether the object implementing the ISecurityElement interface is an instance of the MessageSignature class.

    The following code example checks whether the object is an instance of MessageSignature.

    If TypeOf element Is MessageSignature Then
    
    if (element is MessageSignature)
    
  5. Determine which of the elements that are signed by WSE by default were signed in this SOAP message.

    The SignatureOptions property of the MessageSignature class is a bit field that specifies the elements of a SOAP message that are signed by default.

    The following code example checks whether the <Body> element and the WS-Addressing headers are signed.

    Dim sig As MessageSignature = _
        CType(element, MessageSignature)
    Dim expectedOptions As SignatureOptions = SignatureOptions.IncludeTimestamp Or _
                                              SignatureOptions.IncludeSoapBody Or _
                                              SignatureOptions.IncludeTo Or _
                                              SignatureOptions.IncludeAction Or _
                                              SignatureOptions.IncludeMessageId
    
    If ((sig.SignatureOptions And expectedOptions) = expectedOptions) Then
    
    MessageSignature sig = element as MessageSignature;
    SignatureOptions expectedOptions = SignatureOptions.IncludeTimestamp | 
                                       SignatureOptions.IncludeSoapBody |
                                       SignatureOptions.IncludeTo |
                                       SignatureOptions.IncludeAction |
                                       SignatureOptions.IncludeMessageId;
    
    if ((sig.SignatureOptions & expectedOptions) == expectedOptions)
    

To determine which parts of a SOAP message were encrypted

  1. Create a custom policy assertion.

    For more details about creating custom policy assertions, see How to: Create a Custom Policy Assertion that Secures SOAP Messages.

  2. In the input SOAP filter for the client or the Web service that signs SOAP messages, override the ValidateMessageSecurity method.

    The following code example overrides the SecureMessage method for the output SOAP filter.

    Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
    
    public override void  ValidateMessageSecurity(SoapEnvelope envelope, Security security)
    
  3. Iterate over the Elements collection of the security parameter**.**

    The following code example iterates over the security parameter.

    Dim element As ISecurityElement
    For Each element In security.Elements
    
    foreach (ISecurityElement element in security.Elements)
    {
    
  4. Determine whether the object implementing the ISecurityElement interface is an instance of the EncryptedData class.

    For each element of the SOAP message that is encrypted, there is an instance of EncryptedData in the Elements collection.

    The following code example checks whether the object is an instance of EncryptedData.

    If TypeOf element Is EncryptedData Then
    
    if (element is EncryptedData)
    
  5. Determine which element that is encrypted.

    The following code example checks whether the <Body> element is encrypted.

    Dim encryptedData As EncryptedData = CType(element, EncryptedData)
    Dim targetElement As System.Xml.XmlElement = encryptedData.TargetElement
    
    If (SoapHelper.IsBodyElement(targetElement)) Then
        ' The given context has the Body element Encrypted.
        IsSatisfied = True
    End If
    
    EncryptedData encryptedData = element as EncryptedData;
    System.Xml.XmlElement targetElement = encryptedData.TargetElement;
    
    if (SoapHelper.IsBodyElement(targetElement))
    {
        // The given SOAP message has the Body element Encrypted.
        IsSatisfied = true;
    }
    

Example

The following code example verifies that the <Body> element and the To, Action, MessageID, and From headers are signed using a UsernameToken security token.

Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
    Dim IsSatisfied As Boolean = False
    Dim element As ISecurityElement
    For Each element In security.Elements
        If TypeOf element Is MessageSignature Then
            Dim sig As MessageSignature = _
                CType(element, MessageSignature)
            Dim expectedOptions As SignatureOptions = SignatureOptions.IncludeTimestamp Or _
                                                      SignatureOptions.IncludeSoapBody Or _
                                                      SignatureOptions.IncludeTo Or _
                                                      SignatureOptions.IncludeAction Or _
                                                      SignatureOptions.IncludeMessageId

            If ((sig.SignatureOptions And expectedOptions) = expectedOptions) Then
                ' The SOAP message is signed.
                If TypeOf sig.SigningToken Is UsernameToken Then
                    ' The SOAP message is signed 
                    ' with a UsernameToken.
                    IsSatisfied = True
                End If
            End If
        End If
    Next
    If Not IsSatisfied Then
        Throw New SecurityFault("Signature Requirements not Satisfied")
    End If
End Sub 'ValidateMessageSecurity
public override void  ValidateMessageSecurity(SoapEnvelope envelope, Security security)

{
    bool IsSatisfied = false;
    foreach (ISecurityElement element in security.Elements)
    {
        if (element is MessageSignature)
        {
            MessageSignature sig = element as MessageSignature;
            SignatureOptions expectedOptions = SignatureOptions.IncludeTimestamp | 
                                               SignatureOptions.IncludeSoapBody |
                                               SignatureOptions.IncludeTo |
                                               SignatureOptions.IncludeAction |
                                               SignatureOptions.IncludeMessageId;

            if ((sig.SignatureOptions & expectedOptions) == expectedOptions)
            {
                // The SOAP message is signed.
                if (sig.SigningToken is UsernameToken)
                    // The SOAP message is signed 
                    // with a UsernameToken.
                    IsSatisfied =  true;
            }
        }

    }
    if (!IsSatisfied)
        throw new SecurityFault("Signature Requirements not Satisfied");
}

The following code example checks whether the <Body> element of a SOAP message is encrypted.

Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
    Dim IsSatisfied As Boolean = False
    Dim element As ISecurityElement
    For Each element In security.Elements
        If TypeOf element Is EncryptedData Then
            Dim encryptedData As EncryptedData = CType(element, EncryptedData)
            Dim targetElement As System.Xml.XmlElement = encryptedData.TargetElement

            If (SoapHelper.IsBodyElement(targetElement)) Then
                ' The given context has the Body element Encrypted.
                IsSatisfied = True
            End If
        End If
    Next
    If Not IsSatisfied Then
        Throw New SecurityFault("Signature Requirements not Satisfied")
    End If

End Sub 'ValidateMessageSecurity
public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security)
{
    bool IsSatisfied = false;
    foreach (ISecurityElement element in security.Elements)
    {
        if (element is EncryptedData)
        {
            EncryptedData encryptedData = element as EncryptedData;
            System.Xml.XmlElement targetElement = encryptedData.TargetElement;

            if (SoapHelper.IsBodyElement(targetElement))
            {
                // The given SOAP message has the Body element Encrypted.
                IsSatisfied = true;
            }
        }
    }

    if (!IsSatisfied)
        throw new SecurityFault("Message requirements are not met.");
}

See Also

Tasks

How to: Digitally Sign a SOAP Message
How to: Encrypt a SOAP Message

Other Resources

Signing Custom SOAP Headers