Thursday, June 10, 2010

How to create security tokens for testing purposes?

As part of my work responsibilities I pretty often install different WS-Security implementations to check if they are interoperable or not. If you already have secured client end server the only thing which is necessary is set of security tokens. There are different ways to create security tokens, one of them is openssl tool. OpenSSL is de-facto standard it's usually preinstalled on Unix/Linux systems and could be installed on Windows as well. I use following script to create certificates and keypairs



#create Certificate Authority Key
openssl genrsa -out ca_key.pem $KEYLENGTH
#create Certificate Authoruty Certificate
echo -e "RU\nSpb\nCA\nFAKE CA\nTesters\nCA_example_host\n\n" | \
/usr/bin/openssl req -config $CA_CFG \
-new -x509 -key ca_key.pem -out ca_cert.cer -days $DAYS

for host in $HOSTS
#create key
openssl genrsa -out ${host}_key.pem $KEYLENGTH
#create certificate request, $host is used for CN
echo -e "RU\nSpb\nFAKE Organization\nFAKE Unit\nTesters\n$host\n\n\n\n\n" | \
/usr/bin/openssl req -config $CA_CFG -extensions \
v3_ca -new -key ${host}_key.pem -out ${host}_req.pem -days $DAYS
#create certificate from request
openssl x509 -req -in ${host}_req.pem -out ${host}_cert.cer \
-CA ca_cert.cer -extfile $CA_CFG -extensions v3_ca \
-CAkey ca_key.pem -CAcreateserial -days $DAYS
# delete certificate request
rm ${host}_req.pem
#pack key-pair into pfx file with password $PASS
openssl pkcs12 -export -out ${host}.pfx -passout pass:$PASS \
-inkey ${host}_key.pem -in ${host}_cert.cer
#delete non-encrypted key
rm ${host}_key.pem

This script creates key and self-signed certificate for certificate authority. For each command-line argument script creates key-pair with certificate signed by previously created certificate authority. Certificates are stored in .cer files, keypaires are stored in .pfx files. .cer and.pfx files could be imported into Windows keystore just with doubleckick on .cer/.pfx file and these files could be imported into java keystore with following commands

keytool -importcert -keystore store.jks -storepass password -file certificate.cer
keytool -importkeystore -destkeystore store.jks -deststorepass password \
-srckeystore keypair.pfx -srcstoretype PKCS12 -srcstorepass password

Monday, June 7, 2010

Interop: Microsoft WCF & Intel SOA Expressway

Intel SOA Expressway and Microsoft WCF are supporting wide variety of Web Services standards, both of them supports WS-Security. In this article will be shown how to create and deploy SOA Expressway application to send encrypted and signed requests to WCF-hosted Web-Service.
We will create securing-proxy application for "Intel SOA Expressway". This application will receive plain requests sign/encrypt them and forward secured message to WCF-service, then it will receive encrypted WCF-service response decrypt/verify it and forward plain response to client.

Code of WCF service is listed below

using System;
using System.Configuration;
using System.ServiceModel;
using System.Net.Security;

namespace example {
public interface Example {
string hello(string s);

public class ExampleService : Example {
public string hello(string s) {return "Hello " + s + "!";}
public static void Main() {
using (ServiceHost serviceHost =
new ServiceHost(typeof(ExampleService))) {

Configuration for WCF service
<?xml version="1.0" encoding="utf-8" ?><!--service.exe.config-->
<binding name="free">
<security mode="Message">
<add baseAddress="http://hostname:1234/hello"/>
<endpoint address=""
<endpoint address="mex"
contract="IMetadataExchange" />
<behavior name="behavior">
<serviceMetadata httpGetEnabled="True"
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCertificate storeLocation='CurrentUser'
<authentication trustedStoreLocation='CurrentUser'

We'll need set of security tokens

  • ca_cert.cer - Certificate Authority certificate

  • client_cert.cer - client certificate

  • client.pfx - client key-pair

  • server_cert.cer - server certificate

  • server.pfx - server key-pair

SOA Expressway acts as secured-client it will use

  • ca_cert.cer - to verify response

  • client.pfx - to sign request and to decrypt response

  • server_cert.cer - to encrypt request and verify response

WCF-service acts as secured-server it will use

  • ca_cert.cer - to verify request

  • server.pfx - to sign response and to decrypt request

  • client_cert.cer - to encrypt response and to verify request

First of all we need to get WSDL of Web-Service.
Deploy security tokens into windows keystore (just doubleclick and import them) and compile service.cs with csc.exe, put service.exe.config in directory with service.exe, then
start service.exe; WSDL will become accessible via URL http://hostname:1234/hello?wsdl

Start Intel Services Designer and create new Intel SOA Expressway Project

Create new synchronous workflow

Click on Receive action and select "Use existing WSDL". Click on "Import WSDL" button, select "URL", type "http://hostname:1234/hello?wsdl" and click "Download" button

Workflow's Receive action is bound to service's WSDL. Now we need to create back-end service invocation action. Take "Invoke" action from palette and drop it between Receive and Reply.

Set "Use existing WSDL" checkbox in Properties of Invoke and select "hello" operation

Set Request Message Data parameters field of Invoke action to "$Receive.parameters" to forward client request to back-end server

Click on Reply and set Response Message Data parameters to "$invoke.parameters" to forward response of back-end server to client

Now our workflow is able to receive plain message from client, forward it to back-end server, receive WCF service's response and forward it to client. But WCF service will reject plain messages, so we need to sign/encrypt requests and decrypt/verify responses.
Web-Service is secured with EncryptAndSign protection level it means both request and responses should be Signed then Encrypted together with signature. WCF service uses Basic128Rsa15 algorithmSuite it means it will use aes128 for symmetric encryption, Rsa15 for asymmetric encryption and SHA1 for digest calculation.

We need to create four policies to implement these four actions (sign/encrypt/decrypt/verify)

Create new WS-Security policy with operation type "Sign" and name it "sign"

On "Settings" tab of "sign.wsSecurity" set

  • Signature generation method = rsaWithSha1

  • Digest generation method = sha1

  • Token name = client

WCF doesn't accept messages without singed timestamp, set "Include WS-Security Timestamp in generated signature" checkbox on targets tab of "sign.wsSecurity"

Create new WS-Security policy with operation type "Encrypt" and name it "encrypt". On "Settings" tab of "encrypt.wsSecurity" set

  • Data encryption generation method = aes128

  • Key encryption generation method = rsaV1.5

  • KeyInfo type = SKI

  • Token name = server

By default "Encrypt" policy encrypts only SOAP:Body, but WCF requires signatures to be encrypted as well. On tab "Targets" add namespace "" with prefix "dsig" and add XPath Target Expression /soap:Envelope/soap:Header/wsse:Security/dsig:Signature with Include Tags = Yes

Create new WS-Security policy with operation type "Decrypt" and name it "decrypt". On "Settings" tab of "decrypt.wsSecurity" set

  • Data encryption methods accepted - AES-128

  • Key encryption methods accepted - RSA V1.5

  • Token name - client

Create new WS-Security policy with operation type "Verify" and name it "verify". On "Settings" tab of "verify.wsSecurity" set

  • Signature methods accepted - RSA with SHA1

  • Digest method accepted - SHA1 (160-bit)

  • Canonicalization methods accepted -

  • X509 Certificate Token name - server

  • Authentication Policy Token name - policy

WS-Security policies are ready, now we need to apply them to Invoke action. Open Process.bpel, click on Invoke action then on WS-Security tab of Invoke properties and add sign.wsSecurity, encrypt.wsSecurity to "WS-Security policies for request" table and decrypt.wsSecurrity, verify.wsSecurity to "WS-Security policies for response" table. Order of policies is important, policies are applied to message in same order as they are listed in table.

Workflow is complete now and can be exported for further deployment.

Login to SOAE and go to Configuration tab. Create configuration with name "WCF-example".

Click on "Security Packages" in left column and create new security package with name "example-sec-conf", it will be used to deploy security tokens.

  • Put client.pfx into "Asymmetric Key Pair" section of security configuration with name "client"

  • Put server_cert.cer into "Certificate" section of security configuration with name "server"

  • Put ca_cert.cer into "Trusted CA Group" section of security configuration with name "example-ca"

  • Create new "Web Service Authentication Policy" in security configuration with name "policy" and Trusted CA Group = "example-ca"

Security configuration is ready now, click "OK" to save it, then click on Applications->Upload Application in left column to deploy workflow. Upload application bundle (wcf_example.tgz) and link it to Security Configuration "example-sec-conf"

If Intel SOA Expressway in installed on same machine with WCF Service it's necessary to alter port of Input Server, because default listen port is taken from WSDL is 1234 which is already busy by WCF-service. To alter listen port, click on "Input Servers" in left column, then click on "Edit" in column "Actions", set port 1235 for example.

Click "OK" to save Input Server changes.

Application is deployed and linked to security configuration with necessary tokens. Click "Activate" to save and activate this configuration. After activation Intel SOA Expressway is ready to process request. Let's test it with simple request sent by curl:

[pbtbskaplou /home/bskaplou ]$ cat req
<s:Envelope xmlns:s="">
<s:Body><hello xmlns=""><s>test</s></hello></s:Body>
[pbtbskaplou /home/bskaplou/ ]$ curl -v --data-binary @req -H 'content-type: text/xml' \
-H 'soapaction: ""' \
* About to connect() to pblcbrxw028 port 1235
* Trying connected
* Connected to pblcbrxw028 ( port 1235
> POST /hello HTTP/1.1
> User-Agent: curl/7.15.5
> Host: hostname:1235
> Accept: */*
> content-type: text/xml
> soapaction: ""
> Content-Length: 149
> <s:Envelope xmlns:s="">
<s:Body><hello xmlns="">
< HTTP/1.1 200 OK
< Content-Type: text/xml;charset=utf-8
< Content-Length: 390
<?xml version="1.0" encoding="utf-8"?>
Connection #0 to host hostname left intact
* Closing connection #0
<SOAP:Envelope xmlns:SOAP="">
<helloResult>Hello test!</helloResult></helloResponse></SOAP:Body></SOAP:Envelope>

We've successfully received response from SOA Expressway.