+

Search Tips   |   Advanced Search

Configure signing information using the WSSSignature API

We can secure SOAP messages, without using policy sets for configuration, using the Web Services Security APIs.

To configure signing information for the generator binding sections of the client-side request, use the WSSSignature API, which is part of the package:

To secure SOAP messages:

WAS uses the signing information for the default generator to sign parts of the message, and uses XML digital signature with existing algorithms such as RSA-SHA1 and HMAC-SHA1. XML signature defines methods for describing key information and enables the definition of a new method. XML canonicalization (C14N) is often needed when using XML signature. Information can be represented in various ways within serialized XML documents. The C14N process is used to canonicalize XML information. Select an appropriate C14N algorithm because the information that is canonicalized depends on this algorithm. The signing information specifies the integrity constraints applied to generated messages. The constraints include specifying which message parts within the generated message must be digitally signed, and the message parts to attach digitally signed Nonce and timestamp elements to. The following signature and related signature part information are configured:

For signing information, certain default behaviors occur. The simplest way to use the WSSSignature API is to use the default behavior (see the example code). The default values are defined by the WSS API for the signing method, the canonicalization method, the security token references, and the signature parts.

If WSSSignature.requireSignatureConfirmation() is called, then the WSSSignature API expects that the response message will include the signature confirmation.

  1. To configure signing information in a SOAP message using the WSS API, first ensure that the application server is installed.

  2. Use the WSSSignature API to sign the message parts and specify the algorithms in a SOAP message. The WSS API process for signature follows these process steps:

    1. Uses WSSFactory.getInstance() to get the WSS API implementation instance.

    2. Creates the WSSGenerationContext instance from the WSSFactory instance. WSSGenerationContext must be called in a JAX-WS client application.

    3. Creates the SecurityToken from WSSFactory to configure the key for signing.

    4. Creates WSSSignature from the WSSFactory instance using the SecurityToken. The default behavior of WSSSignature is to sign these signature parts: BODY, ADDRESSING_HEADERS, and TIMESTAMP.

    5. Add the part to be signed, if the default part is not appropriate. If the digest method or transform method is changed, creates WSSSignPart and add it to WSSSignature.

    6. Creates WSSSignaturePart to WSSSignature. Calls the requiredSignatureConfirmation() method, if the signature confirmation is to be applied.

    7. Sets the canonicalization method, if the default is not appropriate.

    8. Sets the signature method, if the default is not appropriate.

    9. Sets the token reference, if the default is not appropriate.

    10. Add WSSSignature to WSSGenerationContext.

    11. Calls WSSGenerationContext.process() with the SOAPMessageContext.


Results

We have completed the steps to configure the signature for the generator section of the bindings. If there is an error condition when signing the message parts, a WSSException is provided. If successful, the WSSGenerationContext.process() is called, and Web Services Security is applied to the SOAP message.


Example

The following example provides sample code that uses methods defined in the WSSignature API.

// Get the message context
   Object msgcontext = getMessageContext();

// Generate the com.ibm.websphere.wssecurity.wssapi.WSSFactory instance  (step: a)
   WSSFactory factory = com.ibm.websphere.wssecurity.wssapi.WSSFactory.getInstance();

// Generate the WSSGenerationContext instance  (step: b)
   WSSGenerationContext gencont = factory.newWSSGenerationContext();

// Generate the callback handler
   X509GenerateCallbackHandler callbackHandler = new 
       X509GenerateCallbackHandler(
       "", "dsig-sender.ks", "jks", 
       "client".toCharArray(), 
       "soaprequester", 
       "client".toCharArray(), 
       "CN=SOAPRequester, OU=TRL, O=IBM, ST=Kanagawa, C=JP", null);

// Generate the security token to be used for the signature  (step: c)
   SecurityToken token = factory.newSecurityToken(X509Token.class, 
        callbackHandler);

// Generate the WSSSignature instance (step: d)
   WSSSignature sig = factory.newWSSSignature(token);

// Set the part to be signed  (step: e)
// DEFAULT: WSSSignature.BODY, WSSSignature.ADDRESSING_HEADERS, 
//          and WSSSignature.TIMESTAMP.

// Set the part in the SOAP Header specified by QName  (step: e)
      sig.addSignHeader(new 
                        QName("http://www.w3.org/2005/08/addressing", 
                        "MessageID"));

// Set the part specified by the keyword  (step: e)
      sig.addSignPart(WSSSignature.BODY);

// Set the part specified by SecurityToken  (step: e)
   UNTGenerateCallbackHandler untCallbackHandler = new 
      UNTGenerateCallbackHandler("Chris", "sirhC");
      SecurityToken unt = factory.newSecurityToken(UsernameToken.class, 
         untCallbackHandler);
      sig.addSignPart(unt);

// Set the part specified by WSSSignPart  (step: e)
   WSSSignPart sigPart = factory.newWSSSignPart();
      sigPart.setSignPart(WSSSignature.TIMESTAMP);
      sigPart.setDigestMethod(WSSSignPart.SHA256);
      sig.addSignPart(sigPart);

// Set the part specified by WSSTimestamp  (step: e)
   WSSTimestamp timestamp = factory.newWSSTimestamp();
      sig.addSignPart(timestamp);

// Set the part specified by XPath expression  (step: e) 
   StringBuffer sb = new StringBuffer();
      sb.append("/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/' 
         and local-name()='Envelope']");
      sb.append("/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/' 
         and local-name()='Body']");
      sb.append("/*[namespace-uri()='http://xmlsoap.org/Ping' 
         and local-name()='Ping']");
      sb.append("/*[namespace-uri()='http://xmlsoap.org/Ping' 
         and local-name()='Text']");
      sig.addSignPartByXPath(sb.toString());

// Set to apply the signature confirmation  (step: f)
      sig.requireSignatureConfirmation();

// Set the canonicalization method  (step: g)
// DEFAULT: WSSSignature.EXC_C14N
      sig.setCanonicalizationMethod(WSSSignature.C14N);

// Set the signature method  (step: h)
// DEFAULT: WSSSignature.RSA_SHA1
      sig.setSignatureMethod(WSSSignature.HMAC_SHA1);

// Set the token reference  (step: i)
// DEFAULT: SecurityToken.REF_STR
      sig.setTokenReference(SecurityToken.REF_KEYID);
 
// Add the WSSSignature to WSSGenerationContext  (step: j)
   gencont.add(sig);

// Generate the WS-Security header  (step: k)
gencont.process(msgctx);

The X509GenerationCallbackHandler needs the key password because the private key is used for signing.


What to do next

  1. Choose the an alternate algorithm method if required.

  2. Use the WSSVerification API to verify the signature and specify the algorithm methods in the consumer section of the binding. The WSSVerification API is only supported on the response consumer (client side).


Related