Encrypting SOAP Messages
When you use the Web service infrastructure provided by the .NET Framework, Web service calls are not encrypted. That means anyone who understands Internet protocols can read your messages and change them! When such a message is signed with a signature, as shown in the previous section, the attacker has no chance to compromise itbut he can still read the content of the SOAP call!
To avoid this security risk you can encrypt the SOAP bodies of your messages, so that a network sniffer cannot read them. An attacker will see only unimportant chars and will not be able to reconstruct the original SOAP call.
For the encryption of SOAP messages the WSE offers you the following three possibilities:
Use an X.509 certificate
Use a shared secret
Use a custom binary token
The Web service itself must provide a class that implements the interface IDecryptionKeyProvider:
public interface IDecryptionKeyProvider
{
public DecryptionKey GetDecryptionKey(
String algorithmUri,
KeyInfo keyInfo);
}
When the WSE runtime decrypts a SOAP request, it calls the method GetDecryptionKey. This method must return a key that can decrypt the request. If this key cannot, because you perhaps supplied a wrong key, the Web service rejects the request and throws an exception of type SoapException.
The following listing shows the required code to implement the IDecryptionKeyProvider interface. The function GetDecryptionKey returns a key based on the Triple-DES-Algorithm:
public DecryptionKey GetDecryptionKey(String algorithmUri,
KeyInfo keyInfo)
{
byte [] keyBytes = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16 };
byte [] ivBytes = { 1, 2, 3, 4, 5, 6, 7 };
foreach (KeyInfoClause clause in keyInfo)
{
if (((KeyInfoName)clause).Value == Solvion Symmetric
Key)
{
SymmetricAlgorithm algo = new
TripleDESCryptoServiceProvider();
algo.Key = keyBytes;
algo.IV = ivBytes;
SymmetricDecryptionKey key = new
SymmetricDecryptionKey(algo);
return key;
}
}
return null;
}
The class implementing the interface also must be registered in the file web.config, as shown here:
<configuration>
<microsoft.web.services>
<security>
<decryptionKeyProvider
type=WebService1.DecryptionKeyProvider,
WebService1 />
</security>
</microsoft.web.services>
</configuration>
The Web method itself is programmed as simply as possible:
[WebMethod]
public String EncryptedSoapMessage()
{
SoapContext requestContext =
HttpSoapContext.RequestContext;
String strResult = ;
if (requestContext != null)
{
strResult = Hello World from my encrypted Web
service.;
}
return strResult;
}
In the client code, I have written the method GetEncryptionKey, which returns the key for the encryption of the SOAP message. This key is then added to the proxy of the Web service, so that the WSE can encrypt the SOAP call:
private void CallEncryptedSoapMessage()
{
MyProxyClass proxy = new MyProxyClass();
SoapContext requestContext = proxy.RequestSoapContext;
EncryptionKey key = GetEncryptionKey();
try
{
requestContext.Security.Elements.Add(new
EncrytedData(key));
requestContext.Timestamp.Ttl = 60000;
Console.WriteLine(proxy.EncryptedSoapMessage());
}
catch (SoapException ex)
{
Console.WriteLine(ex.Message);
}
}
When you are debugging the Web service call, you can see that the method GetDecryptionKey is called before the Web method is executed. When you provide an incorrect key in the client code, you see that the WSE automatically rejects the call to the Web method. When you take a closer look at the trace files, you see that the whole body of the SOAP request is encrypted and it cannot be decrypted without the right key.
The Cornerstone of the GXA
This article has given you a brief introduction to the WSE and has shown how you can program secure Web services using WS-Security. This current WSE release offers you the possibilities to sign and encrypt Web service requests. Its actual implementation is the cornerstone of the GXA architecture, which provides many more proposal standards for Web services infrastructure issues.