Export (0) Print
Expand All

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

The Web Services Enhancements for Microsoft .NET Framework (WSE) supports signing SOAP messages by using X.509 certificates that meet the following criteria:

  • The certificate must not be expired.
  • The certificate must support digital signatures.
  • The issuer of the certificate must be a trusted root, by default.

The following procedures detail how to use Policy or code to digitally sign a SOAP message using an X.509 certificate in a Visual Studio 2005 project.

To write code to sign a SOAP message by using an X.509 certificate

  1. Obtain the X.509 certificate.

    The client X.509 certificate can be obtained 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 and later all include certificate services that support public key infrastructure (PKI).
    • Set up your own certificate service and do not have the certificates signed.

    Whichever approach you take, the recipient of the SOAP request containing the X.509 certificate must trust the X.509 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.

  2. Create a custom policy assertion.

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

  3. In the output SOAP filter for the client, or the Web service that signs SOAP messages, override the SecureMessage method.

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

    public override void SecureMessage(SoapEnvelope envelope, Security security)
    {
    
    
  4. Add references to the Microsoft.Web.Services3 and System.Web.Services assemblies.

    1. In Solution Explorer, right-click References, and then click Add Reference.
    2. Click the .NET tab, select Microsoft.Web.Services3.dll, and then click Select.
    3. On the .NET tab, select System.Web.Services.dll, and then click Select.
    4. Click OK.
  5. Add Imports or using directives to the top of the file that contains the custom policy assertion.

    1. In Solution Explorer, right-click the file containing the policy assertion 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.
      using System;
      using System.Collections.Generic;
      using System.Text;
      using System.Security.Cryptography.X509Certificates;
      
      using Microsoft.Web.Services3;
      using Microsoft.Web.Services3.Design;
      using Microsoft.Web.Services3.Security;
      using Microsoft.Web.Services3.Security.Tokens;
      
      
      
  6. 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.
      X509Store store = new X509Store(StoreName.My,
        StoreLocation.CurrentUser);
      store.Open(OpenFlags.ReadOnly);
      
      
    2. Select a certificate from the certificate store.
      The certificate can be chosen programmatically by iterating over the System.Security.Cryptography.X509Certificates.X509Certificate2Collection collection or by invoking the System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Find method.
      The following code example retrieves the certificate from the certificate store by using the subject name for the certificate.
      X509Certificate2Collection certs =
          store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
          subjectName, false);
      
      
      
    3. Verify that a certificate exists in the store that matches the specified criteria.
      The certificate must support digital signatures and a private key must be available.
      The following code example determines whether the certificate store contains a certificate that matches the specified subject name.
      X509Certificate2 cert;
      if (certs.Count == 1)
      {
          cert = certs[0];
          securityToken = new X509SecurityToken(cert);
      }
      
      
      The following code example defines a GetSecurityToken method that searches for a specific X.509 certificate based on its subject name in the current user's certificate store.
      public X509SecurityToken GetSecurityToken(string subjectName)
      {
          X509SecurityToken securityToken = null;
          X509Store store = new X509Store(StoreName.My,
            StoreLocation.CurrentUser);
          store.Open(OpenFlags.ReadOnly);
          try
          {
              X509Certificate2Collection certs =
                  store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
                  subjectName, false);
      
              X509Certificate2 cert;
              if (certs.Count == 1)
              {
                  cert = certs[0];
                  securityToken = new X509SecurityToken(cert);
              }
              else
                  securityToken = null;
          }
          catch (Exception ex)
          {
              Console.WriteLine(ex.ToString());
          }
          finally
          {
              if (store != null)
                  store.Close();
          }
          return securityToken;
      }
      
      
  7. In the SecureMessage method, call 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.

    X509SecurityToken signatureToken = GetSecurityToken("CN=WSE2QuickStartClient");
    
    
  8. Add the X.509 certificate to the WS-Security SOAP header.

    security.Tokens.Add(signatureToken);
    
    
  9. Create a new instance of the MessageSignature class by using the X.509 certificate just added to the WS-Security SOAP header.

    For information about signing portions of the SOAP message other than the defaults, see Signing Custom SOAP Headers.

    MessageSignature sig = new MessageSignature(signatureToken);
    
    
  10. Add the digital signature to the WS-Security SOAP header.

    security.Elements.Add(sig);
    
    

Example

The following code example calls the GetSecurityToken method to get an X.509 certificate and then signs the SOAP message using an X509SecurityToken security token.

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;


	
	
	...
	
	
			
        public override void SecureMessage(SoapEnvelope envelope, Security security)
        {
            X509SecurityToken signatureToken = GetSecurityToken("CN=WSE2QuickStartClient");
            if (signatureToken == null)
            {
                throw new SecurityFault("Message Requirements could not be satisfied.");
            }

            // Add the security token.                
            security.Tokens.Add(signatureToken);
            // Specify the security token to sign the message with.
            MessageSignature sig = new MessageSignature(signatureToken);

            security.Elements.Add(sig);

        }
        public X509SecurityToken GetSecurityToken(string subjectName)
        {
            X509SecurityToken securityToken = null;
            X509Store store = new X509Store(StoreName.My,
              StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            try
            {
                X509Certificate2Collection certs =
                    store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
                    subjectName, false);

                X509Certificate2 cert;
                if (certs.Count == 1)
                {
                    cert = certs[0];
                    securityToken = new X509SecurityToken(cert);
                }
                else
                    securityToken = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                if (store != null)
                    store.Close();
            }
            return securityToken;
        }

See Also

Show:
© 2014 Microsoft