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 How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted.

To determine which parts of a SOAP message were signed

  1. Receive the SOAP message.

    If the recipient is a Web service, the code with the Web service method executes when a SOAP message is received. If the recipient is a Web service client, then the code executes when a SOAP response is received.

  2. Iterate over the Elements collection of the Security property of the SoapContext.

    The following code example iterates over the SoapContext for a SOAP request received by a Web service.

    Dim context As SoapContext = RequestSoapContext.Current
    Dim element As ISecurityElement
    For Each element In context.Security.Elements
    
    SoapContext context = RequestSoapContext.Current;
    foreach (ISecurityElement element in context.Security.Elements)
    
  3. 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 ( elment is MessageSignature)
    
  4. Determine which of WSE default elements 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 is signed.

    Dim bodySigned As Boolean = _ 
      ((sig.SignatureOptions And SignatureOptions.IncludeSoapBody)<> 0)
    
    bool bodySigned = 
      ((sig.SignatureOptions & SignatureOptions.IncludeSoapBody) != 0);
    
  5. Determine if any elements are signed that are not signed by WSE by default.

    The following code example iterates over the nondefault elements, if any, that were signed.

    Dim i As Integer
    For i = 0 To sig.SignedInfo.References.Count – 1
    Next i
    
    for(int i = 0; i < sig.SignedInfo.References.Count; i++)
    

To determine which parts of a SOAP message were encrypted

  1. Receive the SOAP message.

    If the recipient is a Web service, the code with the Web service method executes when a SOAP message is received. If the recipient is a Web service client, then the code executes when a SOAP response is received.

  2. Iterate over the Elements collection of the Security property of the SoapContext.

    The following code example iterates over the SoapContext for a SOAP response received by a Web service client. The proxy variable is an instance of the proxy class to the Web service.

    Dim element As ISecurityElement
    For Each element In context.Security.Elements
    Next 
    
    foreach (ISecurityElement element in context.Security.Elements)
    
  3. 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)
    
  4. Determine which element that is encrypted.

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

    Dim encryptedData As encryptedData = element
    Dim targetElement As System.Xml.XmlElement = encryptedData.TargetElement
    
    If (SoapEnvelope.IsSoapBody(targetElement)) Then
        ' The given context has the Body element Encrypted.
        Return encryptedData.SecurityToken
    End If
    
    EncryptedData encryptedData = element as EncryptedData;
    System.Xml.XmlElement targetElement = encryptedData.TargetElement;
    
    if ( SoapEnvelope.IsSoapBody(targetElement))
    {
        // The given context has the Body element Encrypted.
        return encryptedData.SecurityToken;
    }
    

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.

Private Function IsMessageSigned(ByVal context As SoapContext) As Boolean
    Dim element As ISecurityElement
    For Each element In context.Security.Elements
        If (TypeOf (element) Is MessageSignature) Then
            ' The SoapContext contains a MessageSignature element. 
            Dim sign As MessageSignature = element
            If ((sign.SignatureOptions And _
                (SignatureOptions.IncludeSoapBody Or _
                SignatureOptions.IncludeTo Or _
                SignatureOptions.IncludeAction Or _
                SignatureOptions.IncludeMessageId Or _
                SignatureOptions.IncludeFrom)) = _
                (SignatureOptions.IncludeSoapBody Or _
                SignatureOptions.IncludeTo Or _
                SignatureOptions.IncludeAction Or _
                SignatureOptions.IncludeMessageId Or _
                SignatureOptions.IncludeFrom)) Then
                If TypeOf sign.SigningToken Is UsernameToken Then
                    ' The SOAP message is signed with a
                    ' UsernameToken.
                    Return True
                End If
            End If
        End If
    Next
    Return False
End Function
private bool IsMessageSigned(SoapContext context)
{
    foreach (ISecurityElement element in context.Security.Elements)
    {
        if (element is MessageSignature)
        {
            MessageSignature sign = element as MessageSignature;

            if ((sign.SignatureOptions & 
                (SignatureOptions.IncludeSoapBody | 
                SignatureOptions.IncludeTo |
                SignatureOptions.IncludeAction |
                SignatureOptions.IncludeMessageId |
                SignatureOptions.IncludeFrom)) == 
                (SignatureOptions.IncludeSoapBody | 
                SignatureOptions.IncludeTo |
                SignatureOptions.IncludeAction |
                SignatureOptions.IncludeMessageId |
                SignatureOptions.IncludeFrom))
            {
                // The SOAP message is signed.
                if (sign.SigningToken is UsernameToken)
                    // The SOAP message is signed 
                    // with a UsernameToken.
                    return true;
            }
        }
    }
    return false;
}

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

Public Shared Function GetEncryptingToken(ByVal context As SoapContext) As SecurityToken
    Dim element As ISecurityElement
    For Each element In context.Security.Elements
        If (TypeOf (element) Is encryptedData) Then
            Dim encryptedData As encryptedData = element
            Dim targetElement As System.Xml.XmlElement = encryptedData.TargetElement

            If (SoapEnvelope.IsSoapBody(targetElement)) Then
                ' The given context has the Body element Encrypted.
                Return encryptedData.SecurityToken
            End If
        End If
    Next

    Return Nothing
End Function 'GetEncryptingToken
public static SecurityToken GetEncryptingToken(SoapContext context)
{
    foreach (ISecurityElement element in context.Security.Elements)
    {
        if (element is EncryptedData)
        {
            EncryptedData encryptedData = element as EncryptedData;
            System.Xml.XmlElement targetElement = encryptedData.TargetElement;

            if ( SoapEnvelope.IsSoapBody(targetElement))
            {
                // The given context has the Body element Encrypted.
                return encryptedData.SecurityToken;
            }
        }
    }

    return null;
}

See Also

Tasks

How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted
How to: Digitally Sign a SOAP Message
How to: Encrypt a SOAP Message