Wednesday, April 23, 2014

Apache Santuario - XML Security for Java 2.0.0 - part II

In the previous blog post, I covered the new StAX-based (streaming) XML Signature functionality coming in Apache Santuario - XML Security for Java 2.0.0. In this post, I will focus on the new streaming XML Encryption functionality that will also be available in this release.

1) XML Encryption test-cases

I have uploaded some test-cases to github to show how to use the new StAX-based API. The tests and setup mirror the XML Signature testcases that I covered in the previous blog post. There are currently three junit tests in this project:

2) Outbound StAX configuration

To see how to configure the new outbound StAX-based XML Encryption functionality, take a look at the "encryptUsingStax" method used by the tests. The streaming XML Security functionality is configured by populating a XMLSecurityProperties Object. You must typically call the following methods for XML Encryption:
  • properties.setAction(XMLSecurityConstants.Action) - an "Action" to perform, which for XML Encryption purposes is XMLSecurityConstants.ENCRYPT. 
  • properties.setEncryptionKey(Key) - The encrypting key. Typically a SecretKey instance.
  • properties.setEncryptionSymAlgorithm(String) - Symmetric encryption Algorithm to use. The default is AES 256.
  • properties.addEncryptionPart(SecurePart) - Add a SecurePart to encrypt, e.g. encrypt a given QName. 
  • properties.setEncryptionTransportKey(Key) - The key to use to encrypt the secret key (if desired). Either a SecretKey or PublicKey instance.
  • properties.setEncryptionKeyTransportAlgorithm(String) - The encryption key transport algorithm to use, to encrypt the secret key (if desired). Default is RSA OAEP.
  • properties.setEncryptionKeyIdentifier(SecurityTokenConstants.KeyIdentifier) - How to reference the encrypting key/cert. The default is SecurityTokenConstants.KeyIdentifier_IssuerSerial.  
The valid Encryption KeyIdentifier types are:
  • SecurityTokenConstants.KeyIdentifier_KeyValue
  • SecurityTokenConstants.KeyIdentifier_KeyName
  • SecurityTokenConstants.KeyIdentifier_IssuerSerial
  • SecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509KeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509SubjectName
  • SecurityTokenConstants.KeyIdentifier_NoKeyInfo
3) Inbound StAX configuration

To see how to configure the new inbound StAX-based XML Encryption functionality, take a look at the "decryptUsingStAX" method used by the tests. As with encryption creation, it is necessary to create a XMLSecurityProperties Object, and to tell it what "Action" to perform. In addition you must call the following method:
  • properties.setDecryptionKey(Key) - a key to use to decrypt the request.
In addition, it is possible to pass a SecurityEventListener to record what security events were performed (see TestSecurityEventListener used in the tests). This allows the user to check what algorithms were used, what was encrypted etc.

Tuesday, March 18, 2014

Apache Santuario - XML Security for Java 2.0.0

In recent posts I have described some of the new features of the forthcoming Apache WSS4J 2.0.0 release. In particular, I focused on the changes and improvements to the existing "in-memory" (DOM-based) WS-Security implementation. However, the biggest new feature of WSS4J 2.0.0 will be a new streaming (StAX-based) WS-Security stack. In the next couple of posts, we will examine the core streaming XML Security functionality that will be available in the Apache Santuario - XML Security for Java 2.0.0 release.

The existing Apache Santuario - XML Security for Java implementation is DOM-based. What this essentially means is that the complete XML Document must be read into memory before being signed or verified. For large XML Documents this carries a corresponding performance penalty. In addition, it means that XML Signature is not feasible for very large documents. In contrast, the StAX API uses a streaming approach, resulting in very low memory usage.

The streaming XML/WS-Security functionality is split between the Apache Santuario and WSS4J projects. The Apache Santuario project contains the core streaming capabilities for XML Signature and Encryption. The Apache WSS4J project builds on this functionality to deliver a streaming WS-Security stack. The entire streaming security functionality is the work of Marc Giger, who donated his SWSSF project to Apache. Marc has done an outstanding job to implement this technically difficult task, and also to integrate the functionality into existing Apache projects. If you wish to experiment with the new functionality, it is available via the 2.0.0-rc1 release.

1) XML Signature test-cases

In this post we will focus on XML Signature only. I have uploaded some test-cases to github to show how to use the new StAX-based API. There are currently three junit tests in this project:
2) Outbound StAX configuration

To see how to configure the new outbound StAX-based XML Signature functionality, take a look at the "signUsingStAX" method used by the tests. The streaming XML Security functionality is configured by populating a XMLSecurityProperties Object. You must typically call the following methods:
  • properties.setAction(XMLSecurityConstants.Action) - an "Action" to perform, which for XML Signature purposes is XMLSecurityConstants.SIGNATURE. 
  • properties.setSignatureKey(Key) - The signing key. Can be a PrivateKey or SecretKey.
  • properties.setSigningCerts(X509Certificate[]) - The signing certs. May be inserted into the Signature KeyInfo depending on the Signature KeyIdentifier.
  • properties.addSignaturePart(SecurePart) - Add a SecurePart to sign, e.g. sign a given QName. You can also specify a digest method or transform algorithm here. You can also sign the entire request via SecurePart.setSecureEntireRequest(boolean).
  • properties.setSignatureAlgorithm(String) - Signature Algorithm to use. The default depends on the signing key.
  • properties.setSignatureDigestAlgorithm(String) - Signature Digest Algorithm to use. The default is the URI for SHA-1.
  • properties.setSignatureCanonicalizationAlgorithm(String) - The canonicalization algorithm to use. The default is XMLSecurityConstants.NS_C14N_EXCL_OMIT_COMMENTS.
  • properties.setSignatureKeyIdentifier(SecurityTokenConstants.KeyIdentifier) - How to reference the signing key/cert. The default is SecurityTokenConstants.KeyIdentifier_IssuerSerial.  
The valid Signature KeyIdentifier types are:
  • SecurityTokenConstants.KeyIdentifier_KeyValue
  • SecurityTokenConstants.KeyIdentifier_KeyName
  • SecurityTokenConstants.KeyIdentifier_IssuerSerial
  • SecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509KeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509SubjectName
  • SecurityTokenConstants.KeyIdentifier_NoKeyInfo
By default, the Signature Element is attached as the first child of the root document.

3) Inbound StAX configuration

To see how to configure the new inbound StAX-based XML Signature functionality, take a look at the "verifyUsingStAX" method used by the tests. As with signature creation, it is necessary to create a XMLSecurityProperties Object, and to tell it what "Action" to perform. In addition you must call the following method, unless the complete signing key is contained in the Signature KeyInfo:
  • properties.setSignatureVerificationKey(Key) - a key to use to verify the Signature.
In addition, it is possible to pass a SecurityEventListener to record what security events were performed (see TestSecurityEventListener used in the tests). This allows the user to check what keys were used for signature verification, what algorithms were used, what was signed etc. See the verifyUsingStAX method as above for some simple code to check the signing key and the elements that were signed.

Wednesday, March 12, 2014

Apache CXF Authentication and Authorization test-cases

I've recently uploaded some test-cases to github that show different ways to authenticate and authorize a web services invocation using Apache CXF. Each project has the same two simple use-cases:
  • A JAX-WS request where the service requires a WS-Security UsernameToken over TLS.
  • A JAX-WS request where the service requires HTTP Basic Auth over TLS.
Each project has an "AuthenticationTest" that just illustrates some tests (including negative tests) for authentication, and then an "AuthorizationTest" that relies on authorizing the client based on roles that are retrieved as part of the authentication process somehow. The projects are as follows:
  • cxf-ldap: This project uses JAAS to authenticate a user via LDAP to a Apache Directory backend. The roles are also retrieved for the AuthorizationTest.
  • cxf-shiro: This project uses Apache Shiro for authentication and authorization.
  • cxf-spring-security: This project uses Spring Security for authentication and authorization.
  • cxf-syncope: This project uses the REST API of Apache Syncope for authenticating and authorizating users.
Feel free to download and play around with the projects.

Monday, February 17, 2014

Apache WSS4J 2.0.0 - part VI

This is the sixth of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The fifth article looked at support for signing and encrypting message attachments via the SOAP with Attachments (SWA) Profile 1.1 specification, as well as the associated WS-SecurityPolicy expressions to sign and encrypt attachments. This post looks at the WS-SecurityPolicy model in WSS4J 2.0.0 and how it is used by the streaming code to perform real-time policy validation of an incoming message.

1) WS-SecurityPolicy model in WSS4J 2.0.0

The user of a web services stack such as Apache CXF or Apache Axis can use
WS-SecurityPolicy to define security requirements for service requests/responses. All that is required in addition to this is some user-specific configuration such as usernames, keystores, etc. However, WSS4J (1.6.x) had no awareness of whether WS-SecurityPolicy was used to define the security requirements or not. It was up to the web service stack in question to parse the security policy, build a model, and use the model to configure WSS4J appropriately. Then it was also up to the web services stack to go through the security results produced by WSS4J on processing a message, to see if the results conform to the policy or not.

WSS4J 2.0.0 includes a WS-SecurityPolicy model as part of the new module "wss4j-policy" module. This means that all web services stacks that rely on WSS4J to perform WS-Security no longer need their own model. Instead, they can register the Apache Neethi AssertionBuilder implementations in the WSS4J module to be able to handle WS-SecurityPolicy policies.

2) Real time streaming policy validation

The DOM-based WS-Security implementation in WSS4J 2.0.0 is still not WS-SecurityPolicy aware, in other words the web services stack must still parse the model to set up the configuration for WSS4J, and parse the results list to validate the results against the model. However, a significant new feature of WSS4J 2.0.0 is that the new streaming WS-Security implementation has the ability to perform "real-time" validation of a request against the set of applicable WS-SecurityPolicy policies. This means that bogus requests can be rejected quicker that the older DOM-based code, which may help to avoid DoS based scenarios. In the next few blog posts in this series, I'll be looking at the new streaming WS-Security implementation in more detail.

Monday, February 10, 2014

Apache WSS4J 2.0.0 - part V

This is the fifth of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The fourth article looked at the ability to encrypt passwords in Crypto properties files. This post looks at support for signing and encrypting message attachments via the SOAP with Attachments (SWA) Profile 1.1 specification, as well as the associated WS-SecurityPolicy expressions to sign and encrypt attachments. Note that there is no support in WSS4J 1.6.x for signing or encrypting message attachments.

1) Configuring WSS4J to secure message attachments

There are two ways of using WSS4J, via an "action"-driven approach where WSS4J must be explicitly configured to perform all of the desired functionality, and via a WS-SecurityPolicy-based approach, where the web services stack sets up the WSS4J configuration internally based on a security policy. Let's look at how to secure message attachments for both of these approaches:

a) Securing message attachments via the "action" approach

With the "action" approach to using WSS4J, the user specifies the parts to sign or encrypt via the following configuration tags:
  • ConfigurationConstants.SIGNATURE_PARTS ("signatureParts")
  • ConfigurationConstants.ENCRYPTION_PARTS ("encryptionParts")
The value of these tags is a String in a special format that looks something like "{Content}{http://example.org/paymentv2}CreditCard". In this example, the element to be secured has the name "CreditCard" and namespace "http://example.org/paymentv2". "Content" only applies to Encryption, and means that the Content should be encrypted (as opposed to the full "Element").

In WSS4J 2.0.0, it is possible to sign/encrypt all of the attachments by specifying the following as part of signatureParts/encryptionParts: "{}cid:Attachments;". It is not possible to only sign/encrypt individual attachments, it is all or nothing. Here is an Apache CXF client configuration file with an example of this.

b) Securing message attachments via WS-SecurityPolicy

An easier way to use WSS4J is in conjunction with a web services stack such as Apache CXF and a WS-SecurityPolicy-based policy. It is possible to sign/encrypt all attachments via the policies:
  • <sp:SignedParts><sp:Attachments /></sp:SignedParts>
  • <sp:EncryptedParts><sp:Attachments /></sp:EncryptedParts>
In addition, the "<sp:Attachments>" policy for SignedParts only has two optional child policies called "sp13:ContentSignatureTransform" and "sp13:AttachmentCompleteSignatureTransform", which dictate whether the attachment headers are included or not in the Signature.

2) Supplying the message attachments to WSS4J

Part 1 above only covers how to configure WSS4J to sign/encrypt message attachments. It is also necessary to actually supply the message attachment streams to WSS4J. This is done in WSS4J via a CallbackHandler approach. An AttachmentRequestCallback Object is used to retrieve either a particular Attachment (on the receiving side), or all attachments (on the sending side). The user must implement a CallbackHandler that sets a list of Attachments matching this request on the Callback. Correspondingly, there is also a AttachmentResponseCallback, which represents the secured/processed Attachment.

The good news is that if you are using Apache CXF then all of this is taken care of automatically by a CallbackHandler that retrieves and sets CXF message attachments. Therefore if you are using CXF then you can sign/encrypt message attachments just by passing the configuration detailed in part 1 of this post. Finally, there are some system tests available in CXF that show how both the "action" and "policy" based approaches work to secure attachments. The test code is here and the resource/configuration files are here.

Wednesday, February 5, 2014

Apache WSS4J 2.0.0 - part IV

This is the fourth of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The third article looked at some changes in the area of caching tokens to detect replay attacks. This post looks at a new feature of WSS4J 2.0.0, which is the ability to encrypt passwords in Crypto properties files.

1) Crypto properties

Apache WSS4J uses the Crypto interface to get keys and certificates for encryption/decryption and for signature creation/verification. WSS4J currently ships with three implementations:
  • Merlin: The standard implementation, based around two JDK keystores for key/cert retrieval, and trust verification.
  • CertificateStore: Holds an array of X509 Certificates. Can only be used for encryption and signature verification.
  • MerlinDevice: Based on Merlin, allows loading of keystores using a null InputStream - for example on a smart-card device.
Typically, a Crypto implementation is loaded and configured via a Crypto properties file. This tells WSS4J what Crypto implementation to load, as well as implementation-specific properties such as a keystore location, password, default alias to use, etc. A typical example of the contents of a Crypto properties file for Signature creation is as follows:

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin
org.apache.wss4j.crypto.merlin.keystore.type=jks
org.apache.wss4j.crypto.merlin.keystore.password=security
org.apache.wss4j.crypto.merlin.keystore.alias=wss40
org.apache.wss4j.crypto.merlin.keystore.file=keys/wss40.jks

Note that in WSS4J 2.0.0 the "org.apache.ws.security.crypto" prefix used previously is now "org.apache.wss4j.crypto", however both prefixes are accepted by the code.

2) Encrypting passwords in a Crypto properties file

Note in the example above that the password used to load the keystore is in cleartext. One of the new features of Apache WSS4J 2.0.0 is the ability to instead store a (BASE-64 encoded) encrypted version of the keystore password in the Crypto properties file. A new PasswordEncryptor interface is defined to allow for the encryption/decryption of passwords. A default implementation is now provided based on Jasypt called JasyptPasswordEncryptor, which uses "PBEWithMD5AndTripleDES".

The way this works is as follows. The WSPasswordCallback class has an additional "usage" called WSPasswordCallback.PASSWORD_ENCRYPTOR_PASSWORD, which is used to return the password used with a PasswordEncryptor implementation to decrypt encrypted passwords stored in Crypto properties files. When WSS4J is loading a Crypto implementation via a properties file, and it encounters a password encrypted in the format "ENC(encoded encrypted password)", it queries a CallbackHandler for the (master) password to decrypt the encrypted password
using the WSPasswordCallback usage tag given above.

It is possible to pass a custom PasswordEncryptor implementation to WSS4J via the new configuration tag ConfigurationConstants.PASSWORD_ENCRYPTOR_INSTANCE ("passwordEncryptorInstance").

Monday, January 27, 2014

Apache WSS4J 2.0.0 - part III

This is the third of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The second article grouped together some new features that were too small to warrant a separate article on their own. This article will focus on some changes in the area of caching tokens to detect replay attacks.

1) Replay Attack detection in Apache WSS4J 1.6.x

Please see a previous article I wrote which covers what Replay Attacks are, and how to prevent them in Apache CXF (using WSS4J 1.6.x). Essentially, the goal is to ensure that an eavesdropper cannot copy a WS-Security enabled request, and make another successful invocation on a service. Three different types of Replay Attack detection exist in Apache WSS4J:
  • Signed Timestamps
  • UsernameToken nonces
  • SAML OneTimeUse Assertions (see here).
Apache WSS4J 1.6.5 introduced a ReplayCache interface, which can be used for replay attack detection for each individual use-case. In addition, WSS4J 1.6.5 shipped with a sample TreeMap-based implementation, which was not intended for production use. However, caching was not enabled by default in WSS4J itself, but rather was configured in Apache CXF using an Ehcache based solution. Please refer to the original article for more details.

2) Replay Attack detection in Apache WSS4J 2.0.0

A new major version release of Apache WSS4J allows us to shift the Replay Attack implementation from Apache CXF into WSS4J itself, so that other stacks can benefit. WSS4J 2.0.0 will ship with default support for detecting replay attacks for the following three scenarios, without any required configuration changes. The default ReplayCache implementation is based on Ehcache and uses the following configuration.

2.a) Signed Timestamp replay detection

By default, WSS4J 2.0.0 will cache a combination of a Timestamp Created value and the Signature Value that signs the Timestamp, that will be cached until the Timestamp "expiry" is reached (or until the default cache expiry is hit). The reason that the Timestamp must be signed is to preclude the rejection of two requests that have been created at the exact same time. The caching of signed Timestamps can be configured as follows:
  • ConfigurationConstants.TIMESTAMP_CACHE_INSTANCE ("timestampCacheInstance"): This holds a reference to a ReplayCache instance used to cache Timestamp Created Strings. The default instance that is used is the EHCacheReplayCache.
  • ConfigurationConstants.ENABLE_TIMESTAMP_CACHE ("enableTimestampCache"):  Whether to cache Timestamp Created Strings (these are only cached in conjunction with a message Signature). The default value is "true".
2.b) UsernameToken nonce replay detection

By default, WSS4J 2.0.0 will cache UsernameToken nonces, and reject any duplicate value. This can be configured as follows:
  • ConfigurationConstants.NONCE_CACHE_INSTANCE ("nonceCacheInstance"): This holds a reference to a ReplayCache instance used to cache UsernameToken nonces. The default instance that is used is the EHCacheReplayCache.
  • ConfigurationConstants.ENABLE_NONCE_CACHE ("enableNonceCache"):  Whether to cache UsernameToken nonces. The default value is "true".
2.c) SAML OneTimeUse replay detection

By default, WSS4J 2.0.0 will cache SAML 2.0 token identifiers, if the token has a OneTimeUse Condition, and reject any duplicate tokens. This can be configured as follows:
  • ConfigurationConstants. SAML_ONE_TIME_USE_CACHE_INSTANCE ("samlOneTimeUseCacheInstance"): This holds a reference to a ReplayCache instance used to cache SAML2 Token Identifier Strings (if the token contains a OneTimeUse Condition). The default instance that is used is the EHCacheReplayCache.
  • ConfigurationConstants.ENABLE_SAML_ONE_TIME_USE_CACHE ("enableSamlOneTimeUseCache"):  Whether to cache SAML2 Token Identifiers, if the token contains a "OneTimeUse" Condition. The default value is "true".