How to: Encrypt a SOAP Message Using an X.509 Certificate

The Web Services Enhancements for Microsoft .NET (WSE) allows a sender, which can either be an XML Web service or its client, to encrypt portions of the SOAP message by using the public key for the recipient's X.509 certificate. A receiver, which can be either a Web service or its client, then decrypts the message by using the private key for its X.509 certificate. If the recipient is the only one with the private key, it is highly likely that only the recipient can decrypt the message. Therefore, to encrypt the message, the sender must have access to the public key for the recipient's X.509 certificate and the recipient must have access to the private key for the recipient's X.509 certificate.

Optionally, the SOAP message can be signed before or after encrypting the SOAP message. If the SOAP message is signed, the sender signs the SOAP message with an X.509 certificate that it owns and has the private key for. This allows the recipient Web service to verify that the client really sent the message through the use of the public key for the sender's X.509 certificate. If the signature can be verified using the public key, the recipient can assume that the message came from the client. Therefore, to sign the message, the sender must have access to the sender's X.509 certificate and private key and the recipient must have access to the sender's X.509 certificate and public key.

For information about specifying which parts of the SOAP message are encrypted, see How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted.

The following procedures detail how to use Policy or code to encrypt a SOAP message using an X.509 certificate.

To use Policy to encrypt a SOAP message with an X.509 certificate

  1. Add a <Policy> Element (WSE for Microsoft .NET) (1) element to the policy file for the application. Add the <Policy> Element (WSE for Microsoft .NET) (1) element as a child element of the <policies> Element element.

    Use the <Policy> Element (WSE for Microsoft .NET) (1) element to define criteria that a SOAP message must meet. The criteria are specified as child elements of the <Policy> element. The Id attribute is used to name the policy assertion, which is used by the <request> Element (WSE for Microsoft .NET), <response> Element (WSE for Microsoft .NET), and <fault> Element elements to refer to a policy assertion when applying the policy to an endpoint.

    The following code example defines a policy assertion named policy-c0a22319-6b89-49ff-9b82-bdbac5f04618.

    <wsp:Policy wsu:Id="policy-c0a22319-6b89-49ff-9b82-bdbac5f04618"
      xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy"
      xmlns:wsa="https://schemas.xmlsoap.org/ws/2004/03/addressing" >
    
  2. Add a <Confidentiality> Element child element to the <Policy> Element (WSE for Microsoft .NET) (1) element.

    Use the <Confidentiality> Element element to define encryption requirements. The requirements are specified in child elements.

    The following code example specifies that there are encryption requirements.

    <wsp:Policy wsu:Id="policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0"
      xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy">
      <wssp:Confidentiality wsp:Usage="wsp:Required"    xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
    
  3. Add a <KeyInfo> Element (WSE for Microsoft .NET) (1) child element to the <Confidentiality> Element element.

    Use the <KeyInfo> Element (WSE for Microsoft .NET) (1) element to define requirements for security tokens used to encrypt SOAP messages.

    The following code example specifies that there are requirements on security tokens used to encrypt SOAP messages.

                  <wssp:Confidentiality wsp:Usage="wsp:Required"
                    xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
                    <wssp:KeyInfo>
    
    
  4. Add a <SecurityToken> Element child element to the <KeyInfo> Element (WSE for Microsoft .NET) (1) element.

    Use the <SecurityToken> Element element to define requirements on security tokens used to encrypt SOAP messages.

    The following code example specifies that there are requirements on security tokens used to encrypt SOAP messages.

    <wssp:KeyInfo>
      <wssp:SecurityToken>
    
  5. Add a <TokenType> Element child element to the <SecurityToken> Element element and set its value to http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3.

    Use the <TokenType> Element element to specify the type of security token that must be used to encrypt SOAP messages.

    The following code example specifies that an X509SecurityToken must be used to encrypt SOAP messages.

    <wssp:SecurityToken>
      <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wssp:TokenType>
    
  6. Optionally, add a <Claims> Element child element to the <SecurityToken> Element element.

    Use the <Claims> Element element to specify requirements specific to an X.509 certificate. The requirements are specified in the <Role> Element or <SubjectName> Element child elements.

    The following code example specifies that there are specific requirements on the X.509 certificate used to encrypt the SOAP message.

    <wssp:SecurityToken>
      <wssp:Claims>
    
  7. Optionally, add a <SubjectName> Element child element to the <Claims> Element element.

    Use the <SubjectName> Element element to specify that the SOAP message must be encrypted using an X.509 certificate with a specific subject name.

    Note

    When the <SubjectName> element is used to specify the subject name for an X.509 certificate, the value of the element is formatted differently than what appears in the MMC. The value that must be placed in the <SubjectName> element maps to the Subject field that appears on the Details tab of the Certificates snap-in within the MMC. If you copy the value of the Subject field from the MMC, the value has to be reversed prior to placement in the <SubjectName> element. For example, if the value of the Subject field is CN=WSE2QuickStartServer, O=Coho Winery, L=Woodinville, S=WA, C=US, the value that must be added to the <SubjectName> element is C=US, S=WA, L=Woodinville, O=Contoso, CN=Coho Winery.

    The following code example specifies that the SOAP message must be encrypted using the X.509 certificate with a subject name of CN=WSE2QuickStartClient.

    <wssp:Claims>
      <wssp:SubjectName>CN=WSE2QuickStartClient</wssp:SubjectName>
    
  8. Optionally, add a <TokenIssuer> Element (WSE for Microsoft .NET) (1) child element to the <SecurityToken> Element element.

    Use the <TokenIssuer> Element (WSE for Microsoft .NET) (1) element to specify the certification authority that issued the X.509 certificate.

    Note

    The value of the <TokenIssuer> element is formatted differently than what appears in the MMC. The value that must be placed in the <TokenIssuer> element maps to the Issuer field that appears on the Details tab of the Certificates snap-in within the MMC. If you copy the value of the Issuer field from the MMC, the value has to be reversed prior to placement in the <TokenIssuer> element. For example, if the value of the Issuer field is CN=CertServer DC=corp DC=contoso DC=com, the value that must be added to the <TokenIssuer> element is DC=com DC=contoso DC=corp CN=CertServer.

    The following code example specifies that the X.509 certificate that is used to encrypt SOAP messages must have been issued by the DC=com DC=contoso DC=corp CN=CertServer certification authority.

    <wssp:SecurityToken>
      <wssp:TokenIssuer>DC=com DC=contoso DC=corp CN=CertServer</wssp:TokenIssuer>
    
  9. Add a <MessageParts> Element for <Confidentiality> Element element to the <Confidentiality> Element element.

    Use the <MessageParts> element to specify the XML elements that must be encrypted.

    The following code example specifies that the <Body> element is encrypted.

    <wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">
      wsp:Body()
    </wssp:MessageParts>
    
  10. Add an <endpoint> Element element to the <mappings> Element element.

    Use the <endpoint> Element element to apply a policy assertion to an endpoint.

    The following code example sets the default policy for all SOAP messages to the policy-c0a22319-6b89-49ff-9b82-bdbac5f04618 policy assertion.

    <mappings xmlns:wse="https://schemas.microsoft.com/wse/2003/06/Policy">
      <endpoint uri="http://www.cohowinery.com/Service1.asmx">
        <defaultOperation>
          <request policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
          <response policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
          <fault policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
        </defaultOperation>
      </endpoint>
    </mappings>
    
  11. Optionally, add an X509SecurityToken that meets the policy requirements to the PolicyEnforcementSecurityTokenCache to the code where you are sending the SOAP message.

    This step is optional, as WSE will look through the following caches or stores in the specified order to find an X.509 certificate that matches the Policy:

  12. The Tokens collection of the SoapContext associated with the SOAP message.

    1. The PolicyEnforcementSecurityTokenCache token cache.
    2. The certificate store specified in the application's configuration file.

    WSE uses the first X.509 certificate that it finds that matches the policy. Therefore, if you would like to use a specific X.509 certificate to encrypt the SOAP message, add an <SubjectName> Element element that specifies the specific X.509 certificate.

    The following code example adds an X509SecurityToken to the PolicyEnforcementSecurityTokenCache.

To use code to encrypt a SOAP message by using an X.509 certificate

  1. Obtain the recipient's X.509 certificate. If you are signing the X.509 certificate, obtain the receiver's X.509 certificate.

    1. Export the recipient's certificate on their computer.
      To export the certificate, open the Certificates snap-in of the MMC, and then run the Certificate Export Wizard.
    2. Obtain the client X.509 certificate in one of the following ways:
    • Purchase a certificate from a certification authority (CA), such as VeriSign, Inc.
    • Set up your own certificate service and have a CA sign the certificates. Windows 2000 Server, Windows 2000 Advanced Server, and Windows 2000 Datacenter Server all include certificate services that support public key infrastructure (PKI).
    • Set up your own certificate service. In this case, the certificate will not be signed.
      Whichever approach you take, the recipient of the SOAP request containing the X.509 certificate must trust the certificate. This means that the X.509 certificate or an issuer in the certificate chain is in the Trusted People certificate store and that the X.509 certificate is not in the Untrusted Certificates store.
      For more information, see Managing X.509 Certificates.
      In order to use the X.509 certificate for encryption, the Key Usage property of the certificate must include the Data Encipherment attribute.
  2. Install the recipient's X.509 certificate in a sender-accessible certificate store on the sender's computer.

    • To import the certificate, open the Certificates snap-in of the MMC, and then run the Certificate Import Wizard.
      The code example that follows (in step 6) assumes that the certificate is imported into the CurrentUser certificate store.
  3. Open the XML Web service client project in Visual Studio .NET 2003.

  4. Add references to the Microsoft.Web.Services2 and System.Web.Services assemblies.

    1. On the Project menu, click Add Reference.
    2. Click the .NET tab, select Microsoft.Web.Services2.dll, and then click Select.
    3. On the .NET tab, select System.Web.Services.dll, and then click Select.
    4. Click OK.
  5. Add a Web reference to the Web service that is to receive the SOAP message signed with the X.509 certificate.

    1. On the Project menu, click Add Web Reference.
    2. In the Add Web Reference dialog box, type the URL for the Web service in the Address box, and then click the arrow icon.
    3. Verify that the items in the Available references box are the items you want to reference in your project, and then click Add Reference.
  6. Edit the proxy class to derive from the WebServicesClientProtocol class.

    1. In Solution Explorer, right-click the Reference.cs file for the Web reference just added, and then click View Code.

      Note

      If the Reference.cs file containing the proxy class is not visible, click the show all files icon on the Solution Explorer toolbar, and then expand the Reference.map node.

    2. Change the base class of the proxy class to the Microsoft.Web.Services2.WebServicesClientProtocol class.
      This modifies the proxy class to emit routing and security SOAP headers when communicating with the Web service. The following code example modifies a proxy class named Service1 to derive from the Microsoft.Web.Services2.WebServicesClientProtocol class.

      Public Class Service1
        Inherits Microsoft.Web.Services2.WebServicesClientProtocol
      
      public class Service1 : Microsoft.Web.Services2.WebServicesClientProtocol {
      

      Note

      If you select the Update Web Reference option in Visual Studio .NET 2003, the proxy class is regenerated, the base class is reset to the SoapHttpClientProtocol class, and you must change the class that the proxy class derives from again.

  7. Add Imports or using directives to the top of the file that communicates with the Web service.

    1. In Solution Explorer, right-click the file containing the client code, and then click View Code.

    2. At the top of the file, add the Imports or using directives as shown in the following code example.

      Imports Microsoft.Web.Services2
      Imports Microsoft.Web.Services2.Security
      Imports Microsoft.Web.Services2.Security.Tokens
      Imports Microsoft.Web.Services2.Security.X509
      Imports System.Security.Cryptography
      
      using Microsoft.Web.Services2;
      using Microsoft.Web.Services2.Security;
      using Microsoft.Web.Services2.Security.Tokens;
      using Microsoft.Web.Services2.Security.X509;
      using System.Security.Cryptography;
      
  8. Add code to get an X.509 certificate.

    1. Open the certificate store containing the certificate that will be used to sign the SOAP message.
      The following code example opens the certificate store for the currently logged-in user.

      Dim store As X509CertificateStore
      store = X509CertificateStore.CurrentUserStore( _
        X509CertificateStore.MyStore)
      Dim open As Boolean = store.OpenRead()
      
      X509CertificateStore store;
      store = X509CertificateStore.CurrentUserStore(
        X509CertificateStore.MyStore);
      bool open = store.OpenRead();
      
    2. Select a certificate from the certificate store.
      The certificate can be chosen programmatically by iterating over the X509CertificateStore.Certificates collection or by invoking one of the "Find" methods. The X509CertificateStore class supports the methods listed in the following table for finding a certificate.

      Method Description

      FindCertificateByHash

      Finds an X.509 certificate in the store by using the certificate's (SHA-1) hash value.

      FindCertificateByKeyIdentifier

      Finds an X.509certificate in the store by using the certificate's authority key identifier.

      FindCertificateBySubjectName

      Finds an X.509 certificate in the store by using the certificate's name value.

      FindCertificateBySubjectString

      Finds an X.509 certificate in the store by using the certificate's name value. This search uses substring matching.

      The QuickStart Samples contain sample code that shows how to display a dialog box for the user to select the certificate. For more information, see the X509CertificateStoreDialog.cs file in the Samples\QuickStart folder in WSE installation folder.
      The following code example retrieves the certificate from the certificate store by using the hash for the certificate. The hash is the certificate's thumbprint. To obtain a certificate's thumbprint, open the Certificates snap-in of the MMC, and then click the Details tab.

      Dim certHash As Byte() =  {&H98, &HEC, &H8, &H4B, &HA5, &H7A, _
        &H6C, &H2F, &H39, &H26, &HB3, &HA, &H58, &HBF, &H65, &H25, _
        &H61, &HC5, &H64, &H59}
      Dim certs As X509CertificateCollection = _
        store.FindCertificateByHash(certHash);
      
      Dim cert As Microsoft.Web.Services2.Security.X509.X509Certificate _
        = CType(certs(0), _
        Microsoft.Web.Services2.Security.X509.X509Certificate)
      
      byte[] certHash = {0x98, 0xec, 0x08, 0x4b, 0xa5 ,0x7a, 0x6c,
        0x2f, 0x39 ,0x26 ,0xb3 ,0x0a ,0x58, 0xbf ,0x65 ,0x25, 0x61,
        0xc5, 0x64 ,0x59};
      X509CertificateCollection certs =
        store.FindCertificateByHash(certHash);
      
      Microsoft.Web.Services2.Security.X509.X509Certificate cert =
        ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]);
      
    3. Verify that the certificate can be used for signing or encryption, depending on how the certificate will be used.
      When the certificate is used to encrypt the SOAP message, the certificate must support data encryption. To support data encryption, the Key Usage property of the X.509 certificate must include the Data Encipherment attribute. The SupportsDataEncryption property of the X509SecurityToken class indicates whether an X.509 certificate's Key Usage attributes include Data Encipherment.

      The following code example determines whether the certificate supports data encryption or key encipherment.
      
      If cert.SupportsDataEncryption Then
      
      if (cert.SupportsDataEncryption)
      

      The following code example defines a GetSecurityToken method that finds the X.509 certificate based on its thumbprint.

      Public Function GetSecurityToken(IsTokenForSigning As Boolean) As X509SecurityToken
          Dim store As X509CertificateStore
          Dim securityToken As X509SecurityToken = Nothing
          ' Open the certificate store for the currently
          ' logged-in user.
          store = X509CertificateStore.CurrentUserStore( _
            X509CertificateStore.MyStore)
          Dim open As Boolean = store.OpenRead()
          Try
              ' Retrieve the certificate by using its SHA-1 hash.
              Dim certHash As Byte() =  {&H98, &HEC, &H8, &H4B, &HA5, _
                &H7A, &H6C, &H2F, &H39, &H26, &HB3, &HA, &H58, &HBF, _
                &H65, &H25, &H61, &HC5, &H64, &H59}
              Dim certs As X509CertificateCollection = _
                store.FindCertificateByHash(certHash)
              Dim cert As _
               Microsoft.Web.Services2.Security.X509.X509Certificate = _
               CType(certs(0), _
               Microsoft.Web.Services2.Security.X509.X509Certificate) 
              If cert Is Nothing Then
                MessageBox.Show("Could not find X.509 certificate.")
                securityToken = Nothing
              ' If the requested token is for signing, verify that
              ' the certificate supports digital signatures and has 
              ' a private key available.
              ElseIf ((IsTokenForSigning) And
                    (Not cert.SupportsDigitalSignature Or 
                    (cert.Key Is Nothing))) Then
                  MessageBox.Show("The certificate must support " + _
                    "digital signatures and have a private key" + _
                    "available.")
                  securityToken = Nothing
              ' If the requested token is for encryption, verify
              ' that the certificate supports data encryption.
              ElseIf (Not IsTokenForSigning) And _
                     (Not cert.SupportsDataEncryption) Then
                  MessageBox.Show("The certificate must support " + _
                    "data encryption.")
                  securityToken = Nothing '
              Else
                  securityToken = New X509SecurityToken(cert)
              End If
          Finally
              If Not (store Is Nothing) Then
                  store.Close()
              End If
          End Try
          Return securityToken
      End Function
      
      public X509SecurityToken GetSecurityToken(bool IsTokenForSigning) 
      {            
         X509CertificateStore store;
         X509SecurityToken securityToken = null;
         // Open the certificate store for the currently 
         // logged-in user.
         store = X509CertificateStore.CurrentUserStore(
                 X509CertificateStore.MyStore);
         bool open = store.OpenRead();
      
         try 
         {
             // Retrieve the certificate by using its SHA-1 hash.
             byte[] certHash = {0x98, 0xec, 0x08, 0x4b, 0xa5, 0x7a,
                                0x6c, 0x2f, 0x39, 0x26, 0xb3, 0x0a,
                                0x58, 0xbf, 0x65, 0x25, 0x61, 0xc5,
                                0x64, 0x59};
             X509CertificateCollection certs =
                store.FindCertificateByHash(certHash);
      
      Microsoft.Web.Services2.Security.X509.X509Certificate cert =
          ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]);
      
            if (cert == null) 
            {
               MessageBox.Show("Could not find the X.509 certificate.");
               securityToken = null;
            }
           // If the requested token is for signing, verify that 
           // the certificate supports digital signatures and has 
           // a private key available.
           else if ((IsTokenForSigning) &&
                    (!cert.SupportsDigitalSignature || 
                    (cert.Key == null)))
          {
            MessageBox.Show("The certificate must support " + 
               "digital signatures and have a private key available.");
            securityToken = null;
          }
          // If the requested token is for encryption, verify 
          // that the certificate supports data encryption.
          else if (!IsTokenForSigning) && 
                !(cert.SupportsDataEncryption)
          {
            MessageBox.Show("The certificate must support data 
                             encryption.");
            securityToken = null;
          }
          else 
          {
             securityToken = new X509SecurityToken(cert);
          }
         } 
         finally 
         {
            if (store != null) { store.Close(); }
         }
         return securityToken;            
      }
      
  9. Edit the method that communicates with the Web service to get the X.509 certificate and specify that the SOAP request be encrypted and optionally signed by the X.509 certificate.

    For information about encrypting portions of the SOAP message other than the defaults, see How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted.

    Note

    Even though you typically sign the SOAP message when encrypting it, this is not required. Therefore, steps b through e are optional.

    1. Get the SoapContext method for the SOAP request that is being made to the Web service.
      The following code example gets the SoapContext method for a proxy class named Service1.

      Dim svc As New Service1()
      Dim requestContext As SoapContext = svc.RequestSoapContext
      
      Service1 svc = new Service1();
      SoapContext requestContext = svc.RequestSoapContext;
      
    2. If the SOAP message is being signed, get an X.509 certificate to sign the SOAP message.
      The following code example calls the method defined in the previous step to get the client's X.509 certificate, which has a private key, to sign the SOAP message.

      Dim signatureToken As X509SecurityToken = GetSecurityToken(True)
      
      X509SecurityToken signatureToken = GetSecurityToken(true);
      
    3. If the SOAP message is being signed, add the sender's X.509 certificate to the WS-Security SOAP header.

      requestContext.Security.Tokens.Add(signatureToken)
      
      requestContext.Security.Tokens.Add(signatureToken);
      
    4. If the SOAP message is being signed, create a new instance of the MessageSignature class by using the X.509 certificate just added to the WS-Security SOAP header.

      Dim sig As New MessageSignature(signatureToken)
      
      MessageSignature sig = new MessageSignature(signatureToken);
      
    5. If the SOAP message is being signed, add the MessageSignature class to the WS-Security SOAP header.

      requestContext.Security.Elements.Add(sig)
      
      requestContext.Security.Elements.Add(sig);
      
    6. Get an X.509 certificate to encrypt the SOAP message.
      The following code example calls the method defined in the previous step to get the server's X.509 certificate, which has only a public key, to encrypt the SOAP message.

      Dim encryptionToken As X509SecurityToken = _
        GetSecurityToken(False)
      
      X509SecurityToken encryptionToken = GetSecurityToken(false);
      
    7. Create a new instance of the EncryptedData class by using the X.509 certificate just added to the WS-Security SOAP header.

      Dim enc As New EncryptedData(encryptionToken)
      
      EncryptedData enc = new EncryptedData(encryptionToken);
      
    8. Add the EncryptedData class to the WS-Security SOAP header.

      requestContext.Security.Elements.Add(enc)
      
      requestContext.Security.Elements.Add(enc);
      
    9. Specify the time-to-live (TTL) for the SOAP message to minimize the chance of someone intercepting the message and replaying it.
      The following code example sets the TTL to 1 minute.

      requestContext.Security.Timestamp.TtlInSeconds = 60
      
      requestContext.Security.Timestamp.TtlInSeconds = 60;
      
    10. Call the Web service.

      svc.sayHello()
      
      svc.sayHello();
      

Example

The following code example is a policy file specifying that all SOAP messages sent to the http://www.cohowinery.com/Service1.asmx endpoint must be encrypted using then X.509 certificate that with a subject name WSE2QuickStart.

Note

This code example is designed to demonstrate WSE features and is not intended for production use.

<?xml version="1.0" encoding="utf-8"?>
<policyDocument xmlns="https://schemas.microsoft.com/wse/2003/06/Policy">
  <mappings xmlns:wse="https://schemas.microsoft.com/wse/2003/06/Policy">
    <endpoint uri="http://www.cohowinery.com/Service1.asmx">
      <defaultOperation>
        <request policy="#policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" />
        <response policy="#policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" />
        <fault policy="#policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" />
      </defaultOperation>
    </endpoint>
  </mappings>
  <policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wsp:Policy wsu:Id="policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0"
      xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy">
      <wssp:Confidentiality wsp:Usage="wsp:Required"
        xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:KeyInfo>
          <SecurityToken xmlns="https://schemas.xmlsoap.org/ws/2002/12/secext">
            <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wssp:TokenType>
                <!-- By specifying the SubjectName claim here, Policy                     can look for a certificate with this subject name                     in the certificate store indicated in the                     application's configuration.                -->                <wssp:SubjectName>CN=WSE2QuickStart</wssp:SubjectName>
          </SecurityToken>
        </wssp:KeyInfo>
        <wssp:MessageParts 
          Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">wsp:Body()</wssp:MessageParts>
      </wssp:Confidentiality>
    </wsp:Policy>
  </policies>
</policyDocument>

The following code example signs and encrypts a SOAP request to a Web service.

Try
    ' Get an X.509 certificate for signing the SOAP message.
    Dim signatureToken As X509SecurityToken = GetSecurityToken(True)
    If signatureToken Is Nothing Then
        Return
    End If
    Dim svc As New Service1()
    Dim requestContext As SoapContext = svc.RequestSoapContext
   
    ' Add the X.509 certificate to the header.
    requestContext.Security.Tokens.Add(signatureToken)

    ' Specify that the SOAP message is signed using this X.509
    ' certifcate.
    Dim sig As New MessageSignature(signatureToken)
    requestContext.Security.Elements.Add(sig)

    ' Get an X.509 certificate for encrypting the SOAP message.
    Dim encryptionToken As X509SecurityToken = _
      GetSecurityToken(False)
    If encryptionToken Is Nothing Then
        Return
    End If
    ' Add the X.509 certificate to the WS-Security header.
    requestContext.Security.Tokens.Add(encryptionToken)
   
    ' Specify that the SOAP message is encrypted using 
    ' this X.509 certificate.
    Dim enc As New EncryptedData(encryptionToken)
    requestContext.Security.Elements.Add(enc)

    ' Set the TTL to 1 minute.
    requestContext.Security.Timestamp.TtlInSeconds = 60
   
    ' Make the SOAP request to the Web service.
    svc.sayHello()
Catch ex As Exception
    MessageBox.Show(ex.ToString())
End Try

Public Function GetSecurityToken(IsTokenForSigning As Boolean) As X509SecurityToken
    Dim store As X509CertificateStore
    Dim securityToken As X509SecurityToken = Nothing
    ' Open the certificate store for the currently
    ' logged-in user.
    store = X509CertificateStore.CurrentUserStore( _
      X509CertificateStore.MyStore)
    Dim open As Boolean = store.OpenRead()
    Try
        ' Retrieve the certificate by using its SHA-1 hash.
        Dim certHash As Byte() =  {&H98, &HEC, &H8, &H4B, &HA5, _
          &H7A, &H6C, &H2F, &H39, &H26, &HB3, &HA, &H58, &HBF, _
          &H65, &H25, &H61, &HC5, &H64, &H59}
        Dim certs As X509CertificateCollection = _
          store.FindCertificateByHash(certHash)
        Dim cert As _
         Microsoft.Web.Services2.Security.X509.X509Certificate = _
         CType(certs(0), _
         Microsoft.Web.Services2.Security.X509.X509Certificate) 
        If cert Is Nothing Then
          MessageBox.Show("Could not find X.509 certificate.")
          securityToken = Nothing
        ' If the requested token is for signing, verify that
        ' the certificate supports digital signatures and has 
        ' a private key available.
        ElseIf ((IsTokenForSigning) And
              (Not cert.SupportsDigitalSignature Or 
              (cert.Key Is Nothing))) Then
            MessageBox.Show("The certificate must support " + _
              "digital signatures and have a private key" + _
              "available.")
            securityToken = Nothing
        ' If the requested token is for encryption, verify
        ' that the certificate supports data encryption.
        ElseIf (Not IsTokenForSigning) And _
               (Not cert.SupportsDataEncryption) Then
            MessageBox.Show("The certificate must support " + _
              "data encryption.")
            securityToken = Nothing '
        Else
            securityToken = New X509SecurityToken(cert)
        End If
    Finally
        If Not (store Is Nothing) Then
            store.Close()
        End If
    End Try
    Return securityToken
End Function
try 
{
    // Get an X.509 certificate for signing the SOAP message.
    X509SecurityToken signatureToken = GetSecurityToken(true);
    if (signatureToken == null) 
    {
        return;
    }
    Service1 svc = new Service1();
    SoapContext requestContext = svc.RequestSoapContext;

    // Add the X.509 certificate to the header.
    requestContext.Security.Tokens.Add(signatureToken);

    // Specify that the SOAP message is signed using this X.509
    // certifcate.
    MessageSignature sig = new MessageSignature(signatureToken);
    requestContext.Security.Elements.Add(sig);

    // Get an X.509 certificate for encrypting the SOAP message.
    X509SecurityToken encryptionToken = GetSecurityToken(false);
    if (encryptionToken == null) 
    {
      return;
    }
    // Add the X.509 certificate to the WS-Security header.
    requestContext.Security.Tokens.Add(encryptionToken);

    // Specify that the SOAP message is encrypted using 
    // this X.509 certificate.
    EncryptedData enc = new EncryptedData(encryptionToken);
    requestContext.Security.Elements.Add(enc);

    // Set the TTL to 1 minute.
    requestContext.Security.Timestamp.TtlInSeconds = 60;

    // Make the SOAP request to the Web service.
    svc.sayHello() ;
}
catch (Exception ex) 
{
    MessageBox.Show(ex.ToString());
}
public X509SecurityToken GetSecurityToken(bool IsTokenForSigning) 
{            
   X509CertificateStore store;
   X509SecurityToken securityToken = null;
   // Open the certificate store for the currently 
   // logged-in user.
   store = X509CertificateStore.CurrentUserStore(
           X509CertificateStore.MyStore);
   bool open = store.OpenRead();

   try 
   {
       // Retrieve the certificate by using its SHA-1 hash.
       byte[] certHash = {0x98, 0xec, 0x08, 0x4b, 0xa5, 0x7a,
                          0x6c, 0x2f, 0x39, 0x26, 0xb3, 0x0a,
                          0x58, 0xbf, 0x65, 0x25, 0x61, 0xc5,
                          0x64, 0x59};
       X509CertificateCollection certs =
          store.FindCertificateByHash(certHash);

Microsoft.Web.Services2.Security.X509.X509Certificate cert =
    ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]);

      if (cert == null) 
      {
         MessageBox.Show("Could not find the X.509 certificate.");
         securityToken = null;
      }
     // If the requested token is for signing, verify that 
     // the certificate supports digital signatures and has 
     // a private key available.
     else if ((IsTokenForSigning) &&
              (!cert.SupportsDigitalSignature || 
              (cert.Key == null)))
    {
      MessageBox.Show("The certificate must support " + 
         "digital signatures and have a private key available.");
      securityToken = null;
    }
    // If the requested token is for encryption, verify 
    // that the certificate supports data encryption.
    else if (!IsTokenForSigning) && 
          !(cert.SupportsDataEncryption)
    {
      MessageBox.Show("The certificate must support data 
                       encryption.");
      securityToken = null;
    }
    else 
    {
       securityToken = new X509SecurityToken(cert);
    }
   } 
   finally 
   {
      if (store != null) { store.Close(); }
   }
   return securityToken;            
}

See Also

Tasks

How to: Decrypt a SOAP Message Encrypted with an X.509 Certificate
How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted

Concepts

Encrypting a SOAP Message

Other Resources

Managing X.509 Certificates