//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//

== Security Best Practices

This section describes a number of steps which should be taken to ensure that security best
practices are followed and enforced.

=== Upgrade to WSS4J 2.3.x or 2.2.x

The 1.5.x and 1.6.x series of releases of WSS4J are deprecated. You should switch to
either 2.3.x or the latest 2.2.x release as a matter of priority, as these
branches contain up to date security fixes. 

=== Upgrade to the latest minor release as soon as possible

You should always upgrade to the latest minor release in a timely manner, in order to pick up 
security fixes.

=== Use WS-SecurityPolicy to enforce security requirements

WSS4J can be used with a web services stack such as Apache CXF or Apache Axis in one of two
ways: either by specifying security actions directly, or via WS-SecurityPolicy. 
WS-SecurityPolicy is a much richer way of specifying security constraints when processing
messages, and gives you more *automatic* protection against various attacks then when
configuring via security actions. See for example, this blog 
http://coheigea.blogspot.ie/2012/10/xml-signature-wrapping-attacks-on-web.html[post]
on XML signature wrapping attacks. Therefore, you should always try to use WSS4J with a
WS-SecurityPolicy requirement.

=== Use RSA-OAEP for the Key Transport Algorithm

WSS4J supports two key transport algorithms, RSA v1.5 and RSA-OAEP. A number
of attacks exist on RSA v1.5. Therefore, you should always use RSA-OAEP as the
key transport algorithm, and enforce this decision. For WS-SecurityPolicy,
this means to avoid using any AlgorithmSuite that ends with "Rsa15" (e.g.
"Basic128Rsa15").

For the "Action" based approach, there are different ways of enforcing that
RSA v1.5 cannot be used for key transport depending on the version of WSS4J.
From WSS4J 2.0.0, it is not allowed by default and no action is required. If you
wish to allow it, then you must set the
WSHandlerConstants.ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM property to "true". For
WSS4J 1.6.x, the RSA v1.5 key transport algorithm is allowed by default. In
this case, you should explicitly configure WSHandlerConstants.ENC_KEY_TRANSPORT
("encryptionKeyTransportAlgorithm") to be
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p". This latter point requires
the web services stack to set this property on the Request (it is known that
Apache CXF does this).

=== Avoid using a cbc Symmetric Encryption Algorithm

There are some attacks that exploit the "cbc" mode of a Symmetric Encryption Algorithm. 
WSS4J has support for "gcm" mode algorithms as well. This can be specified via
WSHandlerConstants.ENC_SYM_ALGO ("encryptionSymAlgorithm"), for example to 
"http://www.w3.org/2009/xmlenc11#aes128-gcm".

=== Use Subject DN regular expressions with chain trust

WSS4J 1.6.7 introduced the ability to specify regular expressions on the Subject DN of a 
certificate used for signature validation. It is important to add this constraint when you
are supporting "chain trust", which is where you are establishing trust in a certificate 
based on the fact that the Issuer of the certificate is in your trust store. Otherwise, any
certificate of this issuer will pass trust validation. See 
http://coheigea.blogspot.ie/2012/08/subject-dn-certificate-constraint.html[here]
for more information. 

=== Specify signature algorithm on receiving side

When not using WS-SecurityPolicy (see point above about favouring the WS-SecurityPolicy
approach), you should specify a signature algorithm to use on the receiving side. This
can be done via WSHandlerConstants.SIG_ALGO ("signatureAlgorithm"). Setting this property
to (e.g.) "http://www.w3.org/2000/09/xmldsig#rsa-sha1" will ensure that the signature
algorithm allowed is RSA-SHA1 and not (e.g.) HMAC-SHA1. This latter point requires the
web services stack to set this property on the Request (it is known that Apache CXF does 
this). See also the previous point about setting the key encryption transport algorithm.

