User login

Secure Message Exchanges with Multiple Users

Story :

Project :

In many practical scenarios a service is expected to encrypt responses to its clients. In such scenarios the service will have to use the client's public key certificate to encrypt the response. It is possible with Apache Axis2 to implement such a scenario in four simple steps using Apache Rampart (the WS-Security module based on Apache WSS4J).

Overview

The overview is as follows, the client sends a message encrypted with the service's public key. The client usually also adds on information about its client certificate or even the whole certificate inside the message. This enables the server to find/use the client's public key to encrypt the response back to the client. The main problem in this scenario is about certificate maintenance. Basically the need to keep adding client certificates to the service's key store when more clients need to access the service. If the client sends its public key in the request, then the server can just peek into the request and extract the public key certificate needed for encrypting the response. The following steps show how we can achieve this using Axis2's Rampart module.

Step 1: Client's Outflow Configuration

For the service to encrypt the response to a certain client, the service should be able to access out the client's public key certificate. The client will send its public key certificate information across to the service by signing the request using its private key, where there will be information available to identify the public key certificate to use in verifying the signature.

An example Rampart outflow configuration to sign a request is as follows:

<parameter name="OutflowSecurity">
<action>
<items>Timestamp Signature Encrypt</items>
<user>client</user>
<encryptionUser>service</encryptionUser>
<signaturePropFile>client.properties</signaturePropFile>
<passwordCallbackClass>org.apache.rampart.samples.reqsigcert.
PWCBHandler</passwordCallbackClass>
<signatureKeyIdentifier>DirectReference</signatureKeyIdentifier>
<signatureParts>{Element}{http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp</signatureParts>
</action>
</parameter>

Note: We add a Timestamp into the message and we sign that Timestamp. This is to make sure this request cannot be replayed again.

Also it's very important that we encrypt the request body sent to the service to prevent a man-in-the-middle attack. If the body is sent as plain text it will allow an attacker to intercept the message, create an appropriate response and return it to the client.

<encryptionUser>service</encryptionUser>

The above "encryptionUser" element specifies the alias of the encryption certificate. In this case the service's public key certificate is available in the keystore under the alias 'service'.

There are few different ways that signature can let the service know about the public key certificate used. This is by the way the key is referenced in by the signature:

  • Reference to a Binary Security Token:
  • Here the public key certificate is available in the request message itself.

    • Reference to a Subject Key Identifier

    This is the value of certificate extension with the object id 2.5.29.14

    • Reference to an Issuer of the Certificate and the Serial Number

    This is a combination of the distinguished name (DN) of the issuer of the public key certificate and the serial number of the certificate

Out of the above three mechanisms "Reference to Subject Key Identifier" and "Reference to an Issuer and the Serial Number" requires the client's certificate to be stored at the service, in addition to the certificate of the issuer of the client certificate. But in the case of the "Reference to a Binary Security Token" there's no need to store the certificate, and we only have to store the certificate of the issuer that issued the certificate. In this case the service will trust all the clients bearing valid signatures created using private keys of which the certificates are signed by the trusted issuer.

Note the "signatureKeyIdentifier" child element of the "action" element in the above configuration.

<signatureKeyIdentifier>DirectReference</signatureKeyIdentifier>

This tells Rampart to add the public key certificate of the client into the message (Security header) as a BinarySecurityToken and to add a reference to it from the signature. This does not require the service to have the client's certificate stored.

In the case the service stores each and every certificate of the clients that it trusts, then the client can use a different reference mechanism as shown below:

  • Reference to an issuer of a certificate and its serial number

Do not use the "signatureKeyIdentifier" child element. This is the default signature key reference reference mechanism.

  • Reference to a Subject Key Identifier
<signatureKeyIdentifier>SKIKeyIdentifier</signatureKeyIdentifier>

In most practical use cases it is not feasible to store and manage all certificates of all trusted clients for a given services. Also it's not feasible to host different services to different clients as well. Therefore, the service can expect the clients to send their certificates in the message itself using the direct reference mechanism that was mentioned earlier. In this case the service will only have to store and manage a list of trusted issuers of certificates (CAs). Any client holding a valid certificate issued by a trusted issuer will be able to access the service.

Step 2: Service Inflow Configuration

Now the service should be configured to accept the signed request. Following is an example Rampart inflow configuration for the service to configure Rampart to accept a Timestamp and to verify the signature.

<parameter name="InflowSecurity">
<action>
<items>Timestamp Signature Encrypt</items>
<passwordCallbackClass>org.apache.rampart.samples.reqsigcert.
PWCBHandler</passwordCallbackClass>
<signaturePropFile>service.properties</signaturePropFile>
</action>
</parameter>

Note: There's no need to specify the reference mechanism of the certificate. Apache Rampart/WSS4J can figure out by processing the Signature element in the Security header.

The client certificate will be extracted and stored in the inflow message context by WSS4J and this will be used by Rampart in the outflow to encrypt the response to the client.

Step 3: Service Outflow Configuration

At this point we have to encrypt the request with the client's certificate. Following is an example outflow configuration for the service:

<parameter name="OutflowSecurity">
<action>
<items>Timestamp Encrypt Signature</items>
<encryptionPropFile>service.properties</encryptionPropFile>
<encryptionKeyIdentifier>SKIKeyIdentifier</encryptionKeyIdentifier>
<encryptionUser>useReqSigCert</encryptionUser>
<user>service</user>
<signaturePropFile>service.properties</signaturePropFile>
<passwordCallbackClass>org.apache.rampart.samples.reqsigcert.
PWCBHandler</passwordCallbackClass>
<signatureParts>{Element}{http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}
{http://schemas.xmlsoap.org/soap/envelope/}Body</signatureParts>
</action>
</parameter>

With the above configuration Rampart will encrypt the Body contents of the SOAP Envelope. The most important item in this is the "encryptionUser" element.

<encryptionUser>useReqSigCert</encryptionUser>

This instructs Rampart/WSS4J to use the certificate that was used to sign the request. One can specify the encrypted parts to encrypt different parts of the message to be encrypted.

It is very important that the service signs the Timestamp and the encrypted body of the response to prevent a third party from sending a bogus encrypted response to the requester. Note that the "user" child element specifies that alias of the private key of the service that is used to sign the response.

Step 4: Client Inflow Configuration

Now we simply have to configure Rampart at the client's inflow to accept an encrypted and signed message, and decrypt it as shown below:

<parametername=InflowSecurity>
<action>
<items>Timestamp Encrypt Signature</items>
<passwordCallbackClass>org.apache.rampart.samples.reqsigcert.PWCBHandler
</passwordCallbackClass>
<decryptionPropFile>client.properties</decryptionPropFile>
<signaturePropFile>client.properties</signaturePropFile>
</action>
</parameter>

Try it out !

You can try this out with the example source code provided here . You will require JDK 1.4 and Apache Ant 1.6.2 or higher as prerequisites.

Simply unzip the "client-cert-encr.zip" and open up two shells within the "client-cert-encr" directory where it contains the Apache Ant build.xml file.

Use one shell to execute the following to start the standalone server hosting the secured service:

$ ant service

Now use the other shell to execute the client using the following:

$ ant client

If you wish to see the message exchange between the client and the service, start the TCPMon tool to listen on port 9090 (example) and redirect the requests to port 8080 of localhost. Then you can change the following property in the build.xml file

<property name="client.port" value="8080"/>

to

<property name="client.port" value="9090"/>

Now when you run the client you will be able to see the messages exchanged.

The keystore used by the service contains the client's certificate and the certificate of the issuer. Therefore, even though the default configuration provided with the sample uses a reference to a binary security token, you can try out the other signature key reference mechanisms by changing the client's configuration parameters available in "client-cert-encr/reqsigcert/client.axis2.xml" file. The service configuration is available in "client-cert-encr/reqsigcert/services.xml".

Author

Ruchith Fernando, Senior Software Engineer, WSO2 Inc. ruchithf at apache dot org

5
Average: 5 (1 vote)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Source Code Link Broken

The link to download the source for this tutorial is broken! Please fix it. Thanks.

Re: Source Code Link Broken

Re: Source Code Link Broken

The link is broken. Could you update the link for downloading the file. Thanks a lot.

Link broken cannot downlod the zip file

Cannot access http://tools.wso2.net/~ruchith/client-cert-encr.zip. Is that only me ?

Pavan

Broken Link

Hi Ruchith,
Can you please fix this link.
http://tools.wso2.net/~ruchith/client-cert-encr.zip
Thanks,
Pavan

xml attributes get lost after encryption

Hi,

I engaged rampart on my server and client web services the exact way that this article and on the client after the message is decrypted the attributes of the xml elements are lost.

I pasted below an example of the request/response without encryption :

The attributes on MapEntry element entryKey and entryValue are lost when encryption. I only get . Any ida what I'm doing wrong. as you can see I'm not using namespaces on my messages.


==============
Listen Port: 9080
Target Host: metvault1.rap.ucar.edu
Target Port: 8080
==== Request ====
POST /axis2/services/MetvaultMetadataService HTTP/1.0

User-Agent: Axis2

SOAPAction: getAllowedValuesSet

Host: metvault1.rap.ucar.edu:9080

Content-Length: 3198

Content-Type: text/xml; charset=UTF-8

<?xml version='1.0' encoding='UTF-8'?>

MIIC7DCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQQFADBNMQswCQYDVQQGEwJMSzEQMA4GA1UE
CBMHV2VzdGVybjEQMA4GA1UEBxMHQ29sb21ibzENMAsGA1UEChMEV1NPMjELMAkGA1UEAxMCQ0EwHhcNMDYwNzIxMTAwOTIx
WhcNMDcwNzIxMTAwOTIxWjBOMQswCQYDVQQGEwJMSzEQMA4GA1UECBMHV2VzdGVybjENMAsGA1UEChMEV1NPMjENMAsGA1UE
CxMEV1NPMjEPMA0GA1UEAxMGQ2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLZbE6nuAkO6f4xEAmjwkbt83/
kLZOC09h8XIzTpNgowkSE7fEffmZ55auT4kr+ZlQWPntN6yUL3UdjCjswzgb6YxCYXAN+AIwdEDfHiY2LEhWJIUi4wxvELEB
ohUOtvFD6U/Wb3bp0inHW9kjueqvTQPvY/E+DxWJtdcAAPbIKQIDAQABo4HaMIHXMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgEN
BB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQxLMCTSZb+3pG0f+eXvVT8HWn7UDB9BgNVHSME
djB0gBTqjpU/ODKOIhKC4vphl14m26jJh6FRpE8wTTELMAkGA1UEBhMCTEsxEDAOBgNVBAgTB1dlc3Rlcm4xEDAOBgNVBAcT
B0NvbG9tYm8xDTALBgNVBAoTBFdTTzIxCzAJBgNVBAMTAkNBggkAo5RPqifQLL0wDQYJKoZIhvcNAQEEBQADgYEAdqTpO79R
lL+e50rmK+tcEhB/SJw4cwXCtHWkloLdrIcdRxl6uDEZBGacxyQtBeLbgTp7jCTKLPuhJ7Hhguyp2ggr26a/Prt32zsu5XTU
VIQMrZLJ2CemA0sOS8UJ7KSvG1ksE38whcFJnaGMbGdP5H2hzDpgQ1DAN38D/eQr3dI=

PqetxDeiqkcl29BADNf1wxTr7G8=

MtBRFwCw5Q3fTxfYwDB3PtNhiV9CTrtb1xaqrFDvpiYxDeRFd/
Mxs/c9dXtniIRA4TWM4oAt0BpsLa4R4spvVXkmXtUdMNvIIToWCfSxB0sCOTWqUrg06z
WgbXqWr6dNXQhRn+EXi0M3Hwi82HR0bjmfWErGshZObRMacRtKJMw=

2006-10-14T00:02:46.142Z
2006-10-14T00:07:46.142Z

data_set.field_type_ids

==== Response ====
HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Set-Cookie: JSESSIONID=CD29816C28329432C20C59D2262D8605; Path=/axis2

Content-Type: multipart/related; boundary=MIMEBoundaryurn_uuid_342DCBF26157F5FF54116078388564219; type="application/xop+xml"; start="<0.urn:uuid:342DCBF26157F5FF54116078388564220@apache.org>"; start-info="text/xml";charset=UTF-8Date: Fri, 13 Oct 2006 23:58:05 GMTConnection: close--MIMEBoundaryurn_uuid_342DCBF26157F5FF54116078388564219content
-type:application/xop+xml; charset=UTF-8; type="text/xml";content-transfer-encoding:binarycontent-id:
<0.urn:uuid:342DCBF26157F5FF54116078388564220@apache.org>
<?xml version='1.0' encoding='UTF-8'?>

7wDCcd/n+3aNtDgeg0vw/0Zi+9E=

7xoB0SBNiiIf8OFFjfRGDAM3UJc=

c0ebXNOyVwVSXaah9KfokWqGDAQ=

biT3GUKXUmKO3Jym4IqVkZrQIvEeRK5QyKRr0UY9J8j2s
BTWhYEK3c9TRHBAlwUJXY+iVBnO76iSOAI4t5QFwItfiUOrrTEkx3fqK6JhVKeP+
yHA07F3n1S/C/GEOyHBKYGU8iy+9sP87HsMrLg5zOatk9wESJsKEOoueumlNEU=

CN=CA,O=WSO2,L=Colombo,ST=Western,C=LK
2

2006-10-13T23:58:05.629Z
2006-10-14T00:03:05.629Z

--MIMEBoundaryurn_uuid_342DCBF26157F5FF54116078388564219--
==============

Thanks,

Marcel Casado

re:xml attributes get lost after encryption

Were you able to make it work ? What is the app server that you are using ?
Pavan

I'm get the nex error

I'm get the nex error deployment de example:

"The signature verification failed (The provided certificate is invalid)"

what I most to do ? 

The signature verification failed - Error

I am encountering the same problem:

"The signature verification failed (The provided certificate is invalid)".

Can anyone please enlighten us regarding what can be the problem? I have investigated if the XML message is changed after it has been signed (by some pretty printing functions or by XML normalization), but it seems that is not the case. Any other ideas?

Any help will be highly appreciated. Thank you!

Re:

If someone else has this problem I think it's probably because the certificates has expired.

try with rampart 1.3

try with rampart 1.3

No luck

I am using rampart 1.3 and I am getting that error. Any other thoughts?

Thanks!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.