Skip navigation

Security by Design

Build Secure Web Services with WS-Security

CoverStory

LANGUAGES: C#

ASP.NET VERSIONS: 1.0 | 1.1

 

Security by Design

Build Secure Web Services with WS-Security

 

By Jeffrey Hasan

 

Many companies have not adopted the Web services technology because it lacks a security specification that can ensure the integrity of transmitted messages and data. The WS-Security specification is a joint effort by several vendors to address this important issue.

 

What do we actually mean when we talk about security ? In broad terms, we are talking about authentication and authorization:

  • Authentication is the process of validating a user s identity based on credentials, or tokens. The token may be a username-password combination, or it may be based on an X.509 certificate. This certificate is a signed public key that has been issued by a certificate authority to vouch for the identity and integrity of a user.
  • Authorization is the process of allowing access to selected resources based on a user s authenticated identity. For example, you can restrict access to a Web service s methods by specific users.

 

Together, authentication and authorization provide for a security model by allowing you to identify a user and then give them selective access to resources.

 

Currently, it is possible to secure SOAP communications over HTTP using the certificate-based Secure Sockets Layer (SSL) protocol. SSL provides encryption and digital signing of both SOAP messages and standard HTTP requests and responses. But SSL has two major limitations that make it unsuitable for securing Web services communications within a service-oriented application. First, SSL is designed for point-to-point communication. However, service-oriented Web services may exchange SOAP messages between two or more endpoints, and so they require a security solution that supports hops across multiple endpoints and multiple domain boundaries. Second, the SSL protocol is built on the HTTP protocol. Web services technology is transport-neutral, and supports message exchange across different protocols, including TCP and SMTP, in addition to HTTP. The SSL protocol is simply too limiting for Web services technology.

 

The WS-Security specification is designed to overcome these limitations and provide an extensible security implementation that will evolve as the Web services technology becomes more sophisticated.

 

The WS-Security Specification

The prime currency in Service Oriented Architecture (SOA) applications are SOAP messages, because they are the means by which requests are made and responses are received from Web service methods. The WS-Security specification provides a way for you to protect the integrity and confidentiality of messages and to implement authentication and authorization models in your Web services. The WS-Security specification enables you to implement the following protections in your Web service calls:

  • Authentication. Security credentials, or tokens, may be exchanged between a client and a Web service to validate the identity of the caller. The tokens are added directly to the header of the SOAP message.
  • Digital Signing. This is the process of signing a SOAP message with a signature that is based on a security token (such as an X.509 certificate). Digital signing creates a cryptographic signature attached to the message that uniquely identifies the sender. The receiver can check this signature to verify the identity of the sender and the integrity of the message. A SOAP exception is raised on the receiving end if anyone tampered with the contents of a SOAP message.
  • Encryption. This is the process of hashing a SOAP message to ensure its confidentiality. There are many available encryption algorithms. In addition, you can encrypt a SOAP message based on an X.509 certificate.

 

The WS-Security specification is platform-independent and transport-neutral, as are all the other WS specifications. Security information is generated by the client and stored within the envelope of the SOAP request message. The Web service in turn will deserialize this information, verify its validity, and process the requested operation. In the event that the message security does not pass verification, the Web service will return a SOAP fault back to the client.

 

Web Services Enhancements (WSE) 2.0 provides the API for implementing WS-Security in .NET-based Web services and client applications. The API allows you to write code to format secured SOAP request messages in the client and process secured messages within a Web service.

 

Implement WS-Security Using WSE 2.0

The focus of this article is to show you how to write the code to implement WS-Security in Web services and their client applications. We will look at two examples:

1)        Digitally sign a SOAP request message with an X.509 certificate.

2)        Encrypt a SOAP request message with an X.509 certificate.

 

Note that WSE 2.0 must be properly installed and configured for the sample projects to work.

 

The WSE 2.0 sample projects ship with test certificates and keys, which we will use here because they are convenient. Here are the installation steps for the sample certificates that ship with WSE 2.0:

1)        Open the MMC console and add the Certificates snap-in for both Current User and Local Machine.

2)        Open the Personal folder of the Current User certificate store and import the sample personal information exchange file entitled Client Private.pfx. This is the private key that the Web service client will use to encrypt requests to the Web service.

3)        Open the Personal folder of the Current User certificate store and import the sample test certificate entitled Server Public.cer. This is the public key that the client uses to digitally sign requests for the Web service.

4)        Open the Personal folder of the Local Machine certificate store and import the sample test certificate entitled Server Public.cer. This is the public key that the Web service uses to decrypt the client s request.

 

After the certificates are installed, you re ready to create Web service clients and services that exchange digitally signed and encrypted SOAP requests. (Note that SOAP responses may also be encrypted; however, that topic is beyond the scope of this article.)

 

How to Digitally Sign SOAP Messages

A digital signature is essentially a cryptographic hash that is added to a SOAP message, and is based on a security token. Digital signatures may be generated using several token types, including an X.509 certificate. The certificate is used to generate a pair of related keys, called the private and public keys. The private key is known only to the client and is used for the following purposes:

  • To digitally sign an outgoing SOAP request message.
  • To decrypt an incoming SOAP response message.

 

The public key is made available to authorized services, which use it for the following purposes:

  • To verify an incoming signed SOAP request message.
  • To encrypt an outgoing SOAP response message.

 

The digital signing process with X.509 certificates works as follows:

1)     The client obtains an X.509 certificate and generates a private-public key pair. The service receives a copy of the public key.

2)     The client applies a hash algorithm to the message, which creates a so-called message digest.

3)     The client then encrypts the message digest with their private key, which creates the digital signature.

4)     The client attaches the digital signature to the SOAP request message. (Programmatically, WSE performs steps 3 and 4 together.)

5)     The client sends the SOAP request message out to the service.

6)     The service receives the SOAP message and checks the security token type.

7)     After the service determines that an X.509 certificate was used, it decrypts the message signature using the public key. This process allows the service to retrieve the original message hash. If the decryption process fails, then the service assumes that the client is not the original sender of the message, or the message has been tampered with, and a SOAP exception is raised.

8)     The service then generates its own message digest using the same algorithm that the client used.

9)     The service compares its generated message digest against the one that has been obtained from the client. If the two message digests match, then the signature has passed verification. If it does not, then the service assumes that the message has been tampered with and a SOAP exception is raised.

 

Digital signatures can have real consequences on message delivery if they are not applied correctly, or if the verification process fails, because either of these issues will prevent the service from processing the incoming SOAP request message. In addition, certificates will expire, so verification will fail if the certificate is not current. The X509SecurityToken and X509SecurityCertificate classes both provide a Boolean IsCurrent property that verifies whether a given certificate is still valid.

 

Implement a Web Service that Accepts Digitally Signed Requests

Now let s look at an example Web service and client that implement digital signatures. The full code listing is available for download (see end of article for details), so to preserve space I ll simply highlight parts of the code. Consider a Web service that provides stock ticker information. Figure 1 shows the required Web.config file settings for the Web service.

 

 

   

    type="Microsoft.Web.Services2.Configuration.

    WebServicesConfiguration, Microsoft.Web.Services2,

     Version=2.0.0.0, Culture=neutral, PublicKeyToken=

    31bf3856ad364e35" />

 

 

   

     

       

     

   

 

 

   

     

      "StockTrader.CustomUsernameTokenManager,

       StockTraderSecure" xmlns:wsse=

       "http://docs.oasis-open.org/wss/2004/01/

       oasis-200401-wss-wssecurity-secext-1.0.xsd"

       qname="wsse:UsernameToken" />

 allowRevocationUrlRetrieval="false" verifyTrust="false" />

   

 

Figure 1: Web.config settings for the secure Web service project.

 

The element contains a sub-element that registers a custom manager class for processing security tokens. It also contains a sub-element called with attributes that allow this project to use unverified test root certificates. Without this setting your Web service calls will generate a SOAP exception alerting you that your certificate is not valid. The element also contains an important attribute called storeLocation, which specifies the location of the certificate that is used to validate or decrypt incoming requests.

 

Modify the Web Service to Process Signed SOAP Messages

The Web service must be modified to iterate through the collection of signatures and tokens that are assigned to a SOAP request message. It is in fact possible to add multiple tokens and signatures to a single message, although the code listings shown here do not do this. The Web service should process the signed SOAP message as follows:

1)     Loop through the collection of signatures attached to the SOAP message.

2)     For each signature in the collection, determine on which type of token it is based.

3)     For username tokens, implement a custom token manager to validate the token.

 

Figure 2 shows you how to loop through the collection of signatures and tokens attached to a SOAP request message. Note that this code listing is implemented directly inside the RequestQuote Web method so that a SOAP fault may be raised directly from the method should the user fail to be authenticated or authorized to access the method.

 

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Web.Services.Description;

using System.Xml.Serialization;

using Microsoft.Web.Services2;

using Microsoft.Web.Services2.Security;

using Microsoft.Web.Services2.Security.Tokens;

using System.Security.Permissions;

using StockTraderTypes;

[WebService()]

public class StockTraderService :

 System.Web.Services.WebService, IStockTrader

{

  [WebMethod()]

 public override Quote RequestQuote(string Symbol)

 {

// Initialize the custom token manager, in case it's needed

 CustomUsernameTokenManager objMgr =

   new CustomUsernameTokenManager();

// Verify the signature on the Web service

// request to this method

 bool SignatureIsValid = false;

 SoapContext requestContext =

   RequestSoapContext.Current;

   foreach (ISecurityElement objElem in

            requestContext.Security.Elements)

   {

     if (objElem is MessageSignature)

     {

       MessageSignature clientSignature =

          (MessageSignature)objElem;

   if (clientSignature.SigningToken is X509SecurityToken)

       {

       SignatureIsValid = true;

       }

   else if (clientSignature.SigningToken is UsernameToken)

       {

       SignatureIsValid = true;

       objMgr.VerifyToken( clientSignature.SigningToken );

       }

     }

   }

// Proceed with request if signature is valid

 Quote q = new Quote();

 if (SignatureIsValid) {}

// Implementation code for RequestQuote()

 }

 return q;

}

Figure 2: Loop through the collection of signatures and tokens attached to a SOAP request message.

 

Create the Web Service Client

Now let s write a Web service client that generates signed SOAP request messages. Figure 3 shows the portion of the code that retrieves an X.509 certificate and applies it to a SOAP request message as a digital signature.

 

using Microsoft.Web.Services2.Security;

using Microsoft.Web.Services2.Security.Tokens;

using Microsoft.Web.Services2.Security.X509;

X509CertificateStore store;

X509SecurityToken token;

// Open the CurrentUser Certificate Store

store = X509CertificateStore.CurrentUserStore(

 X509CertificateStore.MyStore );

// Retrieve the X509 certificate from the

// CurrentUserStore certificate store

string ClientBase64KeyId = "gBfo0147lM6cKnTbbMSuMVvmFY4=";

X509CertificateCollection certs =

 store.FindCertificateByKeyIdentifier(

 Convert.FromBase64String( ClientBase64KeyId ) );

if (certs.Count > 0)

{

 // Get the first certificate in the collection

 token = new X509SecurityToken(

    ((X509Certificate) certs[0]) );

}

// Add the token and digital signature to the

// SOAP request message

serviceProxy.RequestSoapContext.Security.Tokens.Add( token );

serviceProxy.RequestSoapContext.Security.Elements.Add(

 new MessageSignature( token ) );

// Send the Web service request via the proxy class

// (Code listing not shown here.)

Figure 3: Digitally sign a Web service request using an X.509 certificate.

 

Encrypt SOAP Messages with an X.509 Certificate

Security tokens and digital signing allow you to identify a service requestor, and to determine whether a request message has been tampered with, but they do nothing to protect the contents of a SOAP message from network sniffers. Encryption technology enables you to generate a cryptographic hash of the SOAP message for transport, and to decrypt the message contents at the receiving end.

 

There are two kinds of encryption:

  • Symmetric encryption. Also known as private-key, or shared-secret encryption, this method generates a cryptographic hash using a key that is known to both the sender and the receiver. Symmetric encryption is the least secure encryption method because both sender and receiver must share the same key, and so the encryption is only effective if the key remains secret.
  • Asymmetric encryption. Also known as public-key encryption, this method generates a cryptographic hash based on a private key that is known only to the sender. The receiver is given a public key that will decrypt a message that was hashed with the corresponding private key. Asymmetric encryption is the most secure method, and there are many related encryption methodologies from which to choose, including SHA1 and Triple-DES.

 

Interestingly enough, when a SOAP message is encrypted, only the body of the message gets hashed. If your SOAP message includes custom SOAP header values, then you must encrypt them separately. In the following section we ll review how to encrypt the body of a SOAP message using asymmetric encryption.

 

To get started, you can implement asymmetric encryption as outlined in the following steps:

1)     Generate a private-public key pair based on a digital certificate.

2)     Install the private key in the client s local certificate store.

3)     Install the public key in the server s local certificate store.

4)     Implement code in the Web service client to generate an encrypted SOAP request message.

 

Implement the Web Service Client

The client code for generating encrypted SOAP request messages is very similar to the code for digitally signing messages. The client retrieves the applicable X.509 certificate-based private key from its personal certificate store and then uses this key to generate a hash of the SOAP message. Figure 4 shows you the required code.

 

public void EncryptRequestUsingX509Certificate()

{

// Retrieve the X509 certificate from the

// CurrentUserStore certificate store

X509SecurityToken token;

string ClientBase64KeyId = "gBfo0147lM6cKnTbbMSuMVvmFY4=";

// Open the CurrentUser Certificate Store

X509CertificateStore store;

store = X509CertificateStore.CurrentUserStore(

 X509CertificateStore.MyStore );

// Find the certificate based on the server's

// base64 key identifier

X509CertificateCollection certs =

 store.FindCertificateByKeyIdentifier(

 Convert.FromBase64String( ClientBase64KeyId ) );

if (certs.Count > 0)

{

 // Get the first certificate in the collection

 token = new X509SecurityToken(

    ((X509Certificate) certs[0]) );

}

if (token == null) throw new ApplicationException(

 "Unable to obtain security key.");

StockTraderServiceWse serviceProxy =

 new StockTraderServiceWse();

// Add the certificate key to encrypt the request

serviceProxy.RequestSoapContext.Security.Elements.Add(

 new EncryptedData( token ) );

// Call the Web service RequestQuote() method

Console.WriteLine("Calling {0}", serviceProxy.Url);

WSStockTraderClient.StockTraderEncrypted.Quote strQuote =

 serviceProxy.RequestQuote("MSFT");

// Results

Console.WriteLine("Web Service call successful. Result:");

Console.WriteLine( " " );

Console.WriteLine( "Symbol: " + strQuote.Symbol );

Console.WriteLine( "Price:  " + strQuote.Last );

Console.WriteLine( "Change: " +

                   strQuote.PercentChange + "%");

}

Figure 4: Encrypt a SOAP request message using an X.509 certificate.

 

Certificate-based keys must be retrieved from the certificate store using their base64 key identifier. WSE 2.0 ships with a useful utility called the WSE X.509 Certificate Tool, which allows you to browse certificates for the Current User and Local Machine certificate stores, and to retrieve base64 key identifier information. Figure 5 shows the tool displaying the client private key certificate that is used in the example shown in Figure 4.

 


Figure 5: The WSE X.509 Certificate Tool.

 

Modify the Web Service to Process Encrypted SOAP Messages

For asymmetric encryption, the Web service does not require additional code for processing encrypted SOAP request messages. You must simply ensure that the public key for decryption is installed in the Local Machine certificate store on the same server where the Web service is installed. If the public key is not installed correctly, the client application will receive a SOAP fault indicating a problem on the receiving end. But if the certificates are installed correctly, the WSE 2.0 handlers will automatically decrypt the incoming request for you.

 

From a procedural standpoint you may still want to put code in place in the Web method to verify that the request message is in fact encrypted. Figure 6 shows the policy-oriented code listing for verifying that an incoming request message is encrypted.

 

bool EncryptionIsValid = false;

SoapContext requestContext = RequestSoapContext.Current;

foreach (ISecurityElement objElem in

        requestContext.Security.Elements)

{

 if (objElem is EncryptedData)

 {

    // Encrypted Data exists in the Element collections.

    // Now check if it is the body that was encrypted.

    EncryptedData encData = objElem as EncryptedData;

    if (encData.TargetElement.LocalName == "Body")

    {

       EncryptionIsValid = true;

       // Process the Web service request (code not shown)

    }

 }

}

Figure 6: Code to verify that an incoming request message is encrypted.

 

Conclusion

This article has demonstrated how to use WSE 2.0 and the WS-Security specification to implement several types of security measures in SOAP messages, including:

  • Digital signatures on SOAP messages to detect message tampering.
  • Encryption of SOAP messages (using asymmetric encryption) to protect the contents of a SOAP message from network sniffers.

 

The sample code referenced in this article is available for download.

 

Jeffrey Hasan is president of Bluestone Partners, Inc., an IT solutions company based in Orange County, CA (http://www.bluestonepartners.com). Jeff is an experienced enterprise architect and .NET developer, and is the co-author of several books and articles on .NET technology, including the just-released Expert Service Oriented Architecture in C#: Using the Web Services Enhancements 2.0 (Apress, 2004). Contact Jeff at mailto:[email protected].

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish