Many WS-Security configurations require both client and server to use public/private key pairs, with X.509 certificates to vouch for the ownership of the public keys. This is probably the most widely used technique for signing or encrypting messages with WS-Security, and it does have some advantages. In particular, client certificates provide strong client identity verification and strong signature guarantees on requests. But it also has drawbacks, including the performance overhead of asymmetric encryption and the management headaches of obtaining and maintaining certificates for each client.
"WS-SecureConversation performance" showed how WS-SecureConversation — while still working with client certificates — reduces performance overhead for ongoing message exchanges between client and server by using symmetric encryption. In this article, you'll see how you can go a step further and break free of the need for client certificates in both plain WS-Security and WS-SecureConversation exchanges.
Encrypting and signing without client certificates
Using asymmetric encryption with public/private key pairs for signing and encrypting messages is simple (at least conceptually!). As discussed in "Axis2 WS-Security signing and encryption," you use your private key to sign messages and the recipient's public key to encrypt messages. Anyone with access to your public key (which is generally wrapped within layers of authentication in the form of an X.509 certificate) can verify the signature you generated using your private key, whereas only the owner of the corresponding private key can decrypt a message encrypted with a public key.
If the client doesn't have a public/private key pair, you can't use full asymmetric encryption. The alternative is symmetric encryption, but with symmetric encryption you must have a secret key known only to the parties involved in a message exchange. How can you establish such a secret key?
The technique that WS-Security uses is to have the client generate a secret-key value, which is then encrypted using asymmetric encryption with the server's public key and embedded in the request message in a
<xenc:EncryptedKey> token. The client can use this secret key (or for better security, a separate key derived from the secret key) to encrypt and/or sign the request message, and the server can do the same with the response message. There's no need for the server to send the secret key back to the client, because the client already has it available.
WS-Policy/WS-SecurityPolicy configuration for symmetric encryption using a client-generated key is simple. Listing 1 shows the version used in this article. This policy specifies encryption of message bodies sent in both directions, using a client-generated secret key.
Listing 1. WS-Policy for encrypting all message bodies
<wsp:Policy wsu:Id="SymmEncr" xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:ExactlyOne> <wsp:All> <sp:SymmetricBinding> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:X509Token sp:IncludeToken=".../IncludeToken/Never"> <wsp:Policy> <sp:RequireDerivedKeys/> <sp:RequireThumbprintReference/> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic128Rsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> </wsp:Policy> </sp:SymmetricBinding> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefThumbprint/> <sp:MustSupportRefEncryptedKey/> </wsp:Policy> </sp:Wss11> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
<sp:SymmetricBinding> assertion in the Listing 1 policy is what configures the use of symmetric encryption with a secret key. The embedded
<sp:X509Token> assertion says that a X.509 certificate will be used to protect the transmission of the secret key (that is, encrypt the secret key for transmission), with the certificate identified using a thumbprint reference (essentially a hash value). Client generation of the secret key is implicit in the use of a
<sp:SymmetricBinding> assertion with a
<sp:X509Token> protection token. The other policy assertions specify details of the encryption algorithm and required features, and finally the
<sp:EncryptedParts> assertion says that the SOAP
Body is to be encrypted using the secret key.
As you've seen in earlier articles, run-time parameters for the security handling (such as key stores and passwords) must be defined in an implementation-dependent manner. In this case, the parameters are simple: the client side needs access to a trust store containing the server certificate, and the server side needs access to a key store containing the private key matching the public key in the certificate. See earlier articles in this series for details of how the parameters are passed for each of the stacks.
WS-SecureConversation without client certificates
You can apply the same technique for working without client certificates to the
message exchange between the client and the Security Token Service (STS) when using WS-SecureConversation. (See "WS-Trust and WS-SecureConversation" and "WS-SecureConversation performance" for details of WS-SecureConversation.) To use this approach, you basically substitute the Listing 1 policy into the
<sp:BootstrapPolicy> for the secure conversation. Listing 2 shows how this works, with the
<sp:SymmetricBinding> shown in bold replacing the
<sp:AsymmetricBinding> used in "WS-SecureConversation performance":
Listing 2. WS-Policy for WS-SecureConversation without client certificates
<wsp:Policy wsu:Id="SecureConv" xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:ExactlyOne> <wsp:All> <sp:SymmetricBinding> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:SecureConversationToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:BootstrapPolicy> <wsp:Policy> <sp:SymmetricBinding> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:X509Token sp:IncludeToken=".../IncludeToken/Never"> <wsp:Policy> <sp:RequireDerivedKeys/> <sp:RequireThumbprintReference/> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic128Rsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> </wsp:Policy> </sp:SymmetricBinding> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefThumbprint/> <sp:MustSupportRefEncryptedKey/> </wsp:Policy> </sp:Wss11> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:Policy> </sp:BootstrapPolicy> </wsp:Policy> </sp:SecureConversationToken> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic128Rsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> </wsp:Policy> </sp:SymmetricBinding> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
Besides using a client-generated key for the message exchange with the STS, the Listing 2 policy also differs from those used in "WS-SecureConversation performance" by eliminating the
In theory, this policy should work on any WS-Security and WS-SecureConversation implementation. In practice, some problems occurred when I tried this configuration with the three main open source Java web services stacks. CXF was the only stack that worked with the policy as written. Axis2 didn't work at all, failing with a client-side exception when processing the STS response message. When I changed the bootstrap policy back to asymmetric encryption, Axis2 worked but used WS-Addressing on all messages anyway. Metro also failed; after I added back the
<wsap:UsingAddressing>, it worked with a client-generated key for symmetric encryption in the STS message exchange.
The performance comparisons use the same test code as earlier articles, a seismic data retrieval service. The service uses a database of more than 93,000 earthquakes that occurred worldwide over a period of years. Requests to the service specify a time range and a geographic coordinate range, and the service returns all earthquakes within the specified range. See "The high cost of (WS-)Security" for full details of the test application and a sample request/response message pair.
As in the previous articles, two sets of request sequences are used for the performance tests. The first set uses 1,000 requests, with query parameters adjusted to match a small portion of the entire earthquake database (returning 816 matching earthquakes for the 1,000 requests). The second set uses 100 requests, adjusted to match a larger portion of the database (returning 176,745 matching earthquakes for the 100 requests). These two request sequences emphasize different performance characteristics of web services stacks. The first one shows how quickly stacks process requests with little data, and the second emphasizes the speed of processing data volumes. Each request sequence was run multiple times in different security configurations, with only the best time for each configuration kept in the results. This time, only two security configurations were tested:
- WS-Security with
SymmetricBindingencrypting all request/response message bodies (direct)
- WS-SecureConversation encrypting all request/response message bodies (securconv)
The securconv configuration is essentially the same as the one used in "WS-SecureConversation performance," the only difference being the use of a
SymmetricBinding for the message exchange between the client and the STS with Metro and CXF. Because the tested
SymmetricBinding STS policy didn't work with Axis2, the Axis2 configuration used for the timing tests was the same as in the earlier article. The change to using a
SymmetricBinding for the STS policy is more for demonstration purposes than for any significant impact on performance, so this difference is not important in the results.
The tests were run on a Mandriva 2009.1 32-bit Linux® notebook with a Turion X2 ZM-85 processor and 3GB of RAM, using a Sun (Oracle) Java 1.6.0_10 32-bit JVM. (Note that this is a different system from the one used for performance tests in earlier articles.) The server code was run on Tomcat 6.0.20, configured to use 1024MB of heap, with the client code using 512MB of heap. The web service stack versions tested were:
- Axis2 1.5.1 with the 1.5 release of Rampart
- Metro 2.0
- CXF 2.1.8
If you want to try the tests on your own hardware and JVM, see Download to get the code.
Figure 1 shows the measured times for the small-response test series. As in "WS-SecureConversation performance," Metro is a little faster than CXF (about 10 percent) in the WS-SecureConversation timings. Metro does even better with direct use of symmetric encryption with WS-Security, running about 30 percent faster. (In both of this article's charts, shorter bars are better because they indicate faster times.)
Figure 1. Measured times with small responses
Axis2 results are not included in Figure 1 because of a bug that showed up in the course of the test. The Axis2 test started out running at a reasonable speed but then progressively slowed as the number of iterations increased. The total time to run this test with Axis2 ended up more than 40 times the Metro value. This type of progressive slowing usually indicates an issue such as linear lookups of values being stored by code, in this case within the Axis2 security handling for symmetric encryption (perhaps dealing with the client-generated keys, because a new secret key is generated for each request).
Figure 2 shows the measured times for the large-response test series. Here Metro is again the fastest of the stacks, but CXF comes close — the difference between the two is only about 10 percent. Axis2 is much slower than the other two stacks, as was the case in the WS-Security and WS-SecureConversation tests shown in earlier articles.
Figure 2. Measured times with large responses
These results (except for Axis2) match what you'd expect to see based on the security processing being done. With both security configurations, symmetric encryption is used for the messages exchanged between the client and the service. The big difference between the two is that the WS-Security symmetric encryption configuration uses a new secret key generated by the client for each request/response message pair. This secret key needs to be asymmetrically encrypted using the server's public key and sent as part of the request message, whereas WS-SecureConversation reuses a single secret key across many message pairs. This means the WS-Security configuration adds significant per-request overhead, which shows up mainly in the Figure 1 timings.
The stacks don't support using WS-Security asymmetric encryption for only encrypting a message, instead requiring signing to be done also. This makes it difficult to provide any direct performance comparison, but you can get an idea of the difference by comparing these charts with those from "WS-SecureConversation performance." The earlier article showed that WS-SecureConversation symmetric encryption provides considerably better performance than WS-Security asymmetric encryption, especially for encrypting messages. These results show that WS-Security symmetric encryption with client-generated keys is nearly as fast as WS-SecureConversation, especially for larger messages.
You've seen in this article how symmetric encryption, using client-generated secret keys, can be used to secure message exchanges without the need for client certificates. This approach offers good performance for message exchanges — nearly as good as WS-SecureConversation — when the messages are relatively large. If only a few messages are exchanged between a client and server, client-generated secret keys can deliver even better performance than WS-SecureConversation secret keys (because WS-SecureConversation requires an extra message exchange, between the client and the STS).
Client-generated secret keys can also be used for signing messages. Though not shown in this article, this use of secret keys is essentially the same as the signing example for WS-SecureConversation discussed in "WS-SecureConversation performance." Signing with secret keys inherently provides weaker guarantees of authenticity than signing with private keys, but it can still be useful for ensuring that messages have not been tampered with in transit.
The last several articles of this series have discussed various forms of WS-Security and WS-SecureConversation security for web services, including performance comparisons for the three main Java web services stacks. I'll cover some specialized WS-Security features in future articles, but for now it's time to wrap up the focus on security performance. The next article of the series will detail the structure of WS-Policy documents and the ways that policies can be attached to services in WSDL, with examples of fine-tuning security configuration for Apache Axis2, Metro, and Apache CXF.
|Sample code for this article||j-jws17.zip||5.29MB|
- Axis2: Axis 2 is an open source web services stack from Apache.
- Metro: Metro is an open source web services stack that incorporates the latest reference implementations of the JAXB 2.x and JAX-WS 2.x Java standards.
- CXF: CXF is another open source web services stack from the Apache Software Foundation.
- Understanding Web Services specifications: This series of tutorials introduces many of the important web services standards, including:
- "Understanding Web Services specifications: Web Services Description Language (WSDL)" (Nicholas Chase, developerWorks, July 2006)
- "Understanding Web Services specifications: WS-Security" (Nicholas Chase, developerWorks, August 2006)
- "Understanding Web Services specifications: WS-Policy" (Tyler Anderson, developerWorks, February 2007)
- OASIS Web Services Security (WSS) TC: This is the organization responsible for the WS-Security specification and token profiles. You can find links here to all versions of these standards.
- The W3C Web Services Policy Working Group: This group defines the WS-Policy specification.
- OASIS Web Services Secure Exchange (WS-SX) TC: This organization is responsible for WS-SecurityPolicy, WS-SecureConversation, and WS-Trust.
- developerWorks Java technology zone: Find hundreds of articles about every aspect of Java programming.
- Get involved in the My developerWorks community. Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.