/*
 * 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.
 */
package org.apache.myfaces.application.viewstate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.AccessController;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedExceptionAction;
import java.util.Base64;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.faces.FacesException;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExternalContext;
import javax.servlet.ServletContext;

import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
import org.apache.myfaces.util.lang.Assert;
import org.apache.myfaces.spi.SerialFactory;

/**
 * <p>This Class exposes a handful of methods related to encryption,
 * compression and serialization of the view state.</p>
 * 
 * <ul>
 * <li>ISO-8859-1 is the character set used.</li>
 * <li>GZIP is used for all compression/decompression.</li>
 * <li>Base64 is used for all encoding and decoding.</li>
 * <li>DES is the default encryption algorithm</li>
 * <li>ECB is the default mode</li>
 * <li>PKCS5Padding is the default padding</li>
 * <li>HmacSHA1 is the default MAC algorithm</li>
 * <li>The default algorithm can be overridden using the
 * <i>org.apache.myfaces.ALGORITHM</i> parameter</li>
 * <li>The default mode and padding can be overridden using the
 * <i>org.apache.myfaces.ALGORITHM.PARAMETERS</i> parameter</li>
 * <li>This class has not been tested with modes other than ECB and CBC</li>
 * <li>An initialization vector can be specified via the
 * <i>org.apache.myfaces.ALGORITHM.IV</i> parameter</li>
 * <li>The default MAC algorithm can be overridden using the
 * <i>org.apache.myfaces.MAC_ALGORITHM</i> parameter</li>
 * </ul>
 *
 * <p>The secret is interpretted as base 64 encoded.  In other
 * words, if your secret is "76543210", you would put "NzY1NDMyMTA=" in
 * the deployment descriptor.  This is needed so that key values are not
 * limited to just values composed of printable characters.</p>
 *
 * <p>If you are using CBC mode encryption, you <b>must</b> specify an
 * initialization vector.</p>
 *
 * <p>If you are using the AES algorithm and getting a SecurityException
 * complaining about keysize, you most likely need to get the unlimited
 * strength jurisdiction policy files from a place like
 * http://java.sun.com/j2se/1.4.2/download.html .</p>
 *
 * See org.apache.myfaces.webapp.StartupServletContextListener
 */
public final class StateUtils
{
    private static final Logger log = Logger.getLogger(StateUtils.class.getName());

    public static final String ZIP_CHARSET = "ISO-8859-1";

    public static final String DEFAULT_ALGORITHM = "DES";
    public static final String DEFAULT_ALGORITHM_PARAMS = "ECB/PKCS5Padding";

    public static final String INIT_PREFIX = "org.apache.myfaces.";
    
    /**
     * Indicate if the view state is encrypted or not. By default, encryption is enabled.
     */
    @JSFWebConfigParam(name="org.apache.myfaces.USE_ENCRYPTION",since="1.1",
            defaultValue="true",expectedValues="true,false",group="state")
    public static final String USE_ENCRYPTION = INIT_PREFIX + "USE_ENCRYPTION";
    
    /**
     * Defines the secret (Base64 encoded) used to initialize the secret key
     * for encryption algorithm. See MyFaces wiki/web site documentation 
     * for instructions on how to configure an application for 
     * different encryption strengths.
     */
    @JSFWebConfigParam(name="org.apache.myfaces.SECRET",since="1.1",group="state")
    public static final String INIT_SECRET = INIT_PREFIX + "SECRET";
    
    /**
     * Indicate the encryption algorithm used for encrypt the view state.
     */
    @JSFWebConfigParam(name="org.apache.myfaces.ALGORITHM",since="1.1",
            defaultValue="DES",group="state",tags="performance")
    public static final String INIT_ALGORITHM = INIT_PREFIX + "ALGORITHM";

    /**
     * If is set to "false", the secret key used for encryption algorithm is not cached. This is used
     * when the returned SecretKey for encryption algorithm is not thread safe. 
     */
    @JSFWebConfigParam(name="org.apache.myfaces.SECRET.CACHE",since="1.1",group="state")
    public static final String INIT_SECRET_KEY_CACHE = INIT_SECRET + ".CACHE";
    
    /**
     * Defines the initialization vector (Base64 encoded) used for the encryption algorithm
     */
    @JSFWebConfigParam(name="org.apache.myfaces.ALGORITHM.IV",since="1.1",group="state")
    public static final String INIT_ALGORITHM_IV = INIT_ALGORITHM + ".IV";
    
    /**
     * Defines the default mode and padding used for the encryption algorithm
     */
    @JSFWebConfigParam(name="org.apache.myfaces.ALGORITHM.PARAMETERS",since="1.1",
            defaultValue="ECB/PKCS5Padding",group="state")
    public static final String INIT_ALGORITHM_PARAM = INIT_ALGORITHM + ".PARAMETERS";
    
    /**
     * Defines the factory class name using for serialize/deserialize the view state returned 
     * by state manager into a byte array. The expected class must implement
     * {@link org.apache.myfaces.spi.SerialFactory} interface.
     */
    @JSFWebConfigParam(name="org.apache.myfaces.SERIAL_FACTORY", since="1.1",group="state",tags="performance")
    public static final String SERIAL_FACTORY = INIT_PREFIX + "SERIAL_FACTORY";
    
    /**
     * Indicate if the view state should be compressed before encrypted(optional) and encoded
     */
    @JSFWebConfigParam(name="org.apache.myfaces.COMPRESS_STATE_IN_CLIENT",since="1.1",defaultValue="false",
            expectedValues="true,false",group="state",tags="performance")
    public static final String COMPRESS_STATE_IN_CLIENT = INIT_PREFIX + "COMPRESS_STATE_IN_CLIENT";

    public static final String DEFAULT_MAC_ALGORITHM = "HmacSHA1";

    /**
     * Indicate the algorithm used to calculate the Message Authentication Code that is
     * added to the view state.
     */
    @JSFWebConfigParam(name="org.apache.myfaces.MAC_ALGORITHM",defaultValue="HmacSHA1",
            group="state",tags="performance")
    public static final String INIT_MAC_ALGORITHM = "org.apache.myfaces.MAC_ALGORITHM";
    
    /**
     * Define the initialization code that are used to initialize the secret key used
     * on the Message Authentication Code algorithm
     */
    @JSFWebConfigParam(name="org.apache.myfaces.MAC_SECRET",group="state")
    public static final String INIT_MAC_SECRET = "org.apache.myfaces.MAC_SECRET";

    /**
     * If is set to "false", the secret key used for MAC algorithm is not cached. This is used
     * when the returned SecretKey for mac algorithm is not thread safe. 
     */
    @JSFWebConfigParam(name="org.apache.myfaces.MAC_SECRET.CACHE",group="state")
    public static final String INIT_MAC_SECRET_KEY_CACHE = "org.apache.myfaces.MAC_SECRET.CACHE";
    
    /** Utility class, do not instatiate */
    private StateUtils()
    {
        //nope
    }

    private static void testConfiguration(ExternalContext ctx)
    {

        String algorithmParams = ctx.getInitParameter(INIT_ALGORITHM_PARAM);
        
        if (algorithmParams == null)
        {
            algorithmParams = ctx.getInitParameter(INIT_ALGORITHM_PARAM.toLowerCase());
        }
        String iv = ctx.getInitParameter(INIT_ALGORITHM_IV);
        
        if (iv == null)
        {
            iv = ctx.getInitParameter(INIT_ALGORITHM_IV.toLowerCase());
        }
        
        if (algorithmParams != null && algorithmParams.startsWith("CBC") )
        {
            if(iv == null)
            {
                throw new FacesException(INIT_ALGORITHM_PARAM +
                        " parameter has been set with CBC mode," +
                        " but no initialization vector has been set " +
                        " with " + INIT_ALGORITHM_IV);
            }
        }

    }
    
    public static boolean enableCompression(ExternalContext externalContext)
    {
        Assert.notNull(externalContext, "externalContext");

    
        return "true".equals(externalContext.getInitParameter(COMPRESS_STATE_IN_CLIENT));
    }
    
    public static boolean isSecure(ExternalContext externalContext)
    {
        Assert.notNull(externalContext, "externalContext");
        
        return !"false".equals(externalContext.getInitParameter(USE_ENCRYPTION));
    }

    /**
     * This fires during the Render Response phase, saving state.
     */

    public static final String construct(Object object, ExternalContext ctx)
    {
        byte[] bytes = getAsByteArray(object, ctx);
        if( enableCompression(ctx) )
        {
            bytes = compress(bytes);
        }
        if(isSecure(ctx))
        {
            bytes = encrypt(bytes, ctx);
        }
        bytes = encode(bytes);
        try
        {
            return new String(bytes, ZIP_CHARSET);
        }
        catch (UnsupportedEncodingException e)
        {
            throw new FacesException(e);
        }
    }

    /**
     * Performs serialization with the serialization provider created by the 
     * SerialFactory.  
     * 
     * @param object
     * @param ctx
     * @return
     */
    
    public static final byte[] getAsByteArray(Object object, ExternalContext ctx)
    {
        // get the Factory that was instantiated @ startup
        SerialFactory serialFactory = (SerialFactory) ctx.getApplicationMap().get(SERIAL_FACTORY);
        Assert.notNull(serialFactory, "serialFactory");
        
        try
        {
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
            {
                try (ObjectOutputStream oos = serialFactory.getObjectOutputStream(baos))
                {
                    oos.writeObject(object);
                    oos.flush();

                    return baos.toByteArray();
                }
            }
        }
        catch (IOException e)
        {
            throw new FacesException(e);
        }
    }

    public static byte[] encrypt(byte[] insecure, ExternalContext externalContext)
    {
        Assert.notNull(externalContext, "externalContext");

        testConfiguration(externalContext);
        
        SecretKey secretKey = (SecretKey) getSecret(externalContext);
        String algorithm = findAlgorithm(externalContext);
        String algorithmParams = findAlgorithmParams(externalContext);
        byte[] iv = findInitializationVector(externalContext);
        
        SecretKey macSecretKey = (SecretKey) getMacSecret(externalContext);
        String macAlgorithm = findMacAlgorithm(externalContext);
                
        try
        {
            // keep local to avoid threading issue
            Mac mac = Mac.getInstance(macAlgorithm);
            mac.init(macSecretKey);
            Cipher cipher = Cipher.getInstance(algorithm + '/' + algorithmParams);
            if (iv != null)
            {
                IvParameterSpec ivSpec = new IvParameterSpec(iv);
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
            }
            else
            {
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            }
            if (log.isLoggable(Level.FINE))
            {
                log.fine("encrypting w/ " + algorithm + '/' + algorithmParams);
            }
            
            //EtM Composition Approach
            int macLenght = mac.getMacLength();
            byte[] secure = new byte[cipher.getOutputSize(insecure.length)+ macLenght];
            int secureCount = cipher.doFinal(insecure,0,insecure.length,secure);
            mac.update(secure, 0, secureCount);
            mac.doFinal(secure, secureCount);
                        
            return secure;
        }
        catch (Exception e)
        {
            throw new FacesException(e);
        }
    }

    public static final byte[] compress(byte[] bytes)
    {
        
        try
        {
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
            {
                try (GZIPOutputStream gzip = new GZIPOutputStream(baos))
                {
                    gzip.write(bytes, 0, bytes.length);
                    gzip.finish();
                    gzip.flush();

                    return baos.toByteArray();
                }
            }
        }
        catch (IOException e)
        {
            throw new FacesException(e);
        }
    }

    public static final byte[] encode(byte[] bytes)
    {
        return Base64.getEncoder().encode(bytes);
    }

    /**
     * This fires during the Restore View phase, restoring state.
     */
    public static final Object reconstruct(String string, ExternalContext ctx)
    {
        byte[] bytes;
        try
        {
            if(log.isLoggable(Level.FINE))
            {
                log.fine("Processing state : " + string);
            }

            bytes = string.getBytes(ZIP_CHARSET);
            bytes = decode(bytes);
            if(isSecure(ctx))
            {
                bytes = decrypt(bytes, ctx);
            }
            if( enableCompression(ctx) )
            {
                bytes = decompress(bytes);
            }
            return getAsObject(bytes, ctx);
        }
        catch (Throwable e)
        {
            if (log.isLoggable(Level.FINE))
            {
                log.log(Level.FINE, "View State cannot be reconstructed", e);
            }
            return null;
        }
    }

    public static final byte[] decode(byte[] bytes)
    {
        return Base64.getDecoder().decode(bytes);
    }

    public static final byte[] decompress(byte[] bytes)
    {
        Assert.notNull(bytes, "bytes");

        try
        {
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
            {
                try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes))
                {
                    try (GZIPInputStream gis = new GZIPInputStream(bais))
                    {
                        byte[] buffer = new byte[bytes.length];
                        int length;
                        while ((length = gis.read(buffer)) != -1)
                        {
                            baos.write(buffer, 0, length);
                        }
                    }
                }

                return baos.toByteArray();
            }
        }
        catch (IOException e)
        {
            throw new FacesException(e);
        }
    }
    
    public static byte[] decrypt(byte[] secure, ExternalContext externalContext)
    {
        Assert.notNull(externalContext, "externalContext");

        testConfiguration(externalContext);
                
        SecretKey secretKey = (SecretKey) getSecret(externalContext);
        String algorithm = findAlgorithm(externalContext);
        String algorithmParams = findAlgorithmParams(externalContext);
        byte[] iv = findInitializationVector(externalContext);
        
        SecretKey macSecretKey = (SecretKey) getMacSecret(externalContext);
        String macAlgorithm = findMacAlgorithm(externalContext);

        try
        {
            // keep local to avoid threading issue
            Mac mac = Mac.getInstance(macAlgorithm);
            mac.init(macSecretKey);
            Cipher cipher = Cipher.getInstance(algorithm + '/'
                    + algorithmParams);
            if (iv != null)
            {
                IvParameterSpec ivSpec = new IvParameterSpec(iv);
                cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
            }
            else
            {
                cipher.init(Cipher.DECRYPT_MODE, secretKey);
            }
            if (log.isLoggable(Level.FINE))
            {
                log.fine("decrypting w/ " + algorithm + '/' + algorithmParams);
            }

            //EtM Composition Approach
            int macLenght = mac.getMacLength();
            mac.update(secure, 0, secure.length-macLenght);
            byte[] signedDigestHash = mac.doFinal();

            boolean isMacEqual = true;
            for (int i = 0; i < signedDigestHash.length; i++)
            {
                if (signedDigestHash[i] != secure[secure.length-macLenght+i])
                {
                    isMacEqual = false;
                    // MYFACES-2934 Must compare *ALL* bytes of the hash, 
                    // otherwise a side-channel timing attack is theorically possible
                    // but with a very very low probability, because the
                    // comparison time is too small to be measured compared to
                    // the overall request time and in real life applications,
                    // there are too many uncertainties involved.
                    //break;
                }
            }
            if (!isMacEqual)
            {
                throw new ViewExpiredException();
            }
            
            return cipher.doFinal(secure, 0, secure.length-macLenght);
        }
        catch (Exception e)
        {
            throw new FacesException(e);
        }
    }

    /**
     * Performs deserialization with the serialization provider created from the
     * SerialFactory.
     * 
     * @param bytes
     * @param ctx
     * @return
     */
    
    public static final Object getAsObject(byte[] bytes, ExternalContext ctx)
    {
        ByteArrayInputStream input = null;

        try
        {
            input = new ByteArrayInputStream(bytes);

            // get the Factory that was instantiated @ startup
            SerialFactory serialFactory = (SerialFactory) ctx.getApplicationMap().get(SERIAL_FACTORY);
            
            Assert.notNull(serialFactory, "serialFactory");

            ObjectInputStream s = null;
            Exception pendingException = null;
            try
            {
                s = serialFactory.getObjectInputStream(input); 
                Object object = null;
                if (System.getSecurityManager() != null)
                {
                    final ObjectInputStream finalS = s;

                    //Put IOException and ClassNotFoundException as "checked" exceptions,
                    //so AccessController wrap them in a PrivilegedActionException
                    object = AccessController.doPrivileged((PrivilegedExceptionAction) () -> finalS.readObject());
                }
                else
                {
                    object = s.readObject();
                }
                return object;
            }
            catch (Exception e)
            {
                pendingException = e;
                throw new FacesException(e);
            }
            finally
            {
                if (s != null)
                {
                    try
                    {
                        s.close();
                    }
                    catch (IOException e)
                    {
                        // If a previous exception is thrown 
                        // ignore this, but if not, wrap it in a
                        // FacesException and throw it. In this way
                        // we preserve the original semantic of this
                        // method, but we handle correctly the case
                        // when we close a stream. Obviously, the 
                        // information about this exception is lost,
                        // but note that the interesting information 
                        // is always on pendingException, since we
                        // only do a readObject() on the outer try block.
                        if (pendingException == null)
                        {
                            throw new FacesException(e);
                        }                        
                    }
                    finally
                    {
                        s = null;
                    }
                }
            }
        }
        finally
        {
            if (input != null)
            {
                try
                {
                    input.close();
                }
                catch (IOException e)
                {
                    //ignore it, because ByteArrayInputStream.close has
                    //no effect, but it is better to call close and preserve
                    //semantic from previous code.
                }
                finally
                {
                    input = null;
                }
            }
        }
    }

    /**
     * Utility method for generating base 64 encoded strings.
     * 
     * @param args
     * @throws UnsupportedEncodingException
     */
    public static void main (String[] args) throws UnsupportedEncodingException
    {
        byte[] bytes = encode(args[0].getBytes(ZIP_CHARSET));
          System.out.println(new String(bytes, ZIP_CHARSET));
    }

    private static byte[] findInitializationVector(ExternalContext ctx)
    {
        
        byte[] iv = null;
        String ivString = ctx.getInitParameter(INIT_ALGORITHM_IV);
        
        if(ivString == null)
        {
            ivString = ctx.getInitParameter(INIT_ALGORITHM_IV.toLowerCase());
        }
        
        if (ivString != null)
        {
            iv = decode(ivString.getBytes());
        }
        
        return iv;
    }

    private static String findAlgorithmParams(ExternalContext ctx)
    {
        
        String algorithmParams = ctx.getInitParameter(INIT_ALGORITHM_PARAM);
        
        if (algorithmParams == null)
        {
            algorithmParams = ctx.getInitParameter(INIT_ALGORITHM_PARAM.toLowerCase());
        }
        
        if (algorithmParams == null)
        {
            algorithmParams = DEFAULT_ALGORITHM_PARAMS;
        }
        
        if (log.isLoggable(Level.FINE))
        {
            log.fine("Using algorithm paramaters " + algorithmParams);
        }
        
        return algorithmParams;
    }

    private static String findAlgorithm(ExternalContext ctx)
    {
        
        String algorithm = ctx.getInitParameter(INIT_ALGORITHM);
        
        if (algorithm == null)
        {
            algorithm = ctx.getInitParameter(INIT_ALGORITHM.toLowerCase());
        }

        return findAlgorithm( algorithm );
    }
    
    private static String findAlgorithm(ServletContext ctx)
    {

        String algorithm = ctx.getInitParameter(INIT_ALGORITHM);
        
        if (algorithm == null)
        {
            algorithm = ctx.getInitParameter(INIT_ALGORITHM.toLowerCase());
        }

        return findAlgorithm( algorithm );
    }
    
    private static String findAlgorithm(String initParam)
    {
        
        if (initParam == null)
        {
            initParam = DEFAULT_ALGORITHM;
        }
        
        if (log.isLoggable(Level.FINE))
        {
            log.fine("Using algorithm " + initParam);
        }
        
        return initParam;
        
    }

    /**
     * Does nothing if the user has disabled the SecretKey cache. This is
     * useful when dealing with a JCA provider whose SecretKey 
     * implementation is not thread safe.
     * 
     * Instantiates a SecretKey instance based upon what the user has 
     * specified in the deployment descriptor.  The SecretKey is then 
     * stored in application scope where it can be used for all requests.
     */
    
    public static void initSecret(ServletContext servletContext)
    {
        Assert.notNull(servletContext, "servletContext");
        
        if (log.isLoggable(Level.FINE))
        {
            log.fine("Storing SecretKey @ " + INIT_SECRET_KEY_CACHE);
        }

        // Create and store SecretKey on application scope
        String cache = servletContext.getInitParameter(INIT_SECRET_KEY_CACHE);
        
        if(cache == null)
        {
            cache = servletContext.getInitParameter(INIT_SECRET_KEY_CACHE.toLowerCase());
        }
        
        if (!"false".equals(cache))
        {
            String algorithm = findAlgorithm(servletContext);
            // you want to create this as few times as possible
            servletContext.setAttribute(INIT_SECRET_KEY_CACHE, new SecretKeySpec(
                    findSecret(servletContext, algorithm), algorithm));
        }

        if (log.isLoggable(Level.FINE))
        {
            log.fine("Storing SecretKey @ " + INIT_MAC_SECRET_KEY_CACHE);
        }
        
        String macCache = servletContext.getInitParameter(INIT_MAC_SECRET_KEY_CACHE);
        
        if(macCache == null)
        {
            macCache = servletContext.getInitParameter(INIT_MAC_SECRET_KEY_CACHE.toLowerCase());
        }
        
        if (!"false".equals(macCache))
        {
            String macAlgorithm = findMacAlgorithm(servletContext);
            // init mac secret and algorithm 
            servletContext.setAttribute(INIT_MAC_SECRET_KEY_CACHE, new SecretKeySpec(
                    findMacSecret(servletContext, macAlgorithm), macAlgorithm));
        }
    }
    
    private static SecretKey getSecret(ExternalContext ctx)
    {
        Object secretKey = (SecretKey) ctx.getApplicationMap().get(INIT_SECRET_KEY_CACHE);
        
        if (secretKey == null)
        {
            String cache = ctx.getInitParameter(INIT_SECRET_KEY_CACHE);
            
            if(cache == null)
            {
                cache = ctx.getInitParameter(INIT_SECRET_KEY_CACHE.toLowerCase());
            }
            
            if ("false".equals(cache))
            {
                // No cache is used. This option is activated
                String secret = ctx.getInitParameter(INIT_SECRET);
                
                if (secret == null)
                {
                    secret = ctx.getInitParameter(INIT_SECRET.toLowerCase());
                }

                if (secret == null)
                {
                    throw new NullPointerException("Could not find secret using key '" + INIT_SECRET + '\'');
                }
                
                String algorithm = findAlgorithm(ctx);
                
                secretKey = new SecretKeySpec(findSecret(ctx, algorithm), algorithm);
            }
            else
            {
                throw new NullPointerException("Could not find SecretKey in application scope using key '" 
                        + INIT_SECRET_KEY_CACHE + '\'');
            }
        }
        
        if( ! ( secretKey instanceof SecretKey ) )
        {
            throw new ClassCastException("Did not find an instance of SecretKey "
                    + "in application scope using the key '" + INIT_SECRET_KEY_CACHE + '\'');
        }

        
        return (SecretKey) secretKey;
    }

    private static byte[] findSecret(ExternalContext ctx, String algorithm)
    {
        String secret = ctx.getInitParameter(INIT_SECRET);
        
        if (secret == null)
        {
            secret = ctx.getInitParameter(INIT_SECRET.toLowerCase());
        }
        
        return findSecret(secret, algorithm);
    }    
    
    private static byte[] findSecret(ServletContext ctx, String algorithm)
    {
        String secret = ctx.getInitParameter(INIT_SECRET);
        
        if (secret == null)
        {
            secret = ctx.getInitParameter(INIT_SECRET.toLowerCase());
        }
        
        return findSecret(secret, algorithm);
    }
    
    private static byte[] findSecret(String secret, String algorithm)
    {
        byte[] bytes = null;
        
        if(secret == null)
        {
            try
            {
                KeyGenerator kg = KeyGenerator.getInstance(algorithm);
                bytes = kg.generateKey().getEncoded();
                
                if(log.isLoggable(Level.FINE))
                {
                    log.fine("generated random password of length " + bytes.length);
                }
            }
            catch (NoSuchAlgorithmException e)
            {
                // Generate random password length 8, 
                int length = 8;
                bytes = new byte[length];
                new Random().nextBytes(bytes);
                
                if(log.isLoggable(Level.FINE))
                {
                    log.fine("generated random password of length " + length);
                }
            }
        }
        else 
        {
            bytes = decode(secret.getBytes());
        }
        
        return bytes;
    }

    private static String findMacAlgorithm(ExternalContext ctx)
    {
        
        String algorithm = ctx.getInitParameter(INIT_MAC_ALGORITHM);
        
        if (algorithm == null)
        {
            algorithm = ctx.getInitParameter(INIT_MAC_ALGORITHM.toLowerCase());
        }

        return findMacAlgorithm( algorithm );

    }
    
    private static String findMacAlgorithm(ServletContext ctx)
    {

        String algorithm = ctx.getInitParameter(INIT_MAC_ALGORITHM);
        
        if (algorithm == null)
        {
            algorithm = ctx.getInitParameter(INIT_MAC_ALGORITHM.toLowerCase());
        }

        return findMacAlgorithm( algorithm );
        
    }
    
    private static String findMacAlgorithm(String initParam)
    {
        
        if (initParam == null)
        {
            initParam = DEFAULT_MAC_ALGORITHM;
        }
        
        if (log.isLoggable(Level.FINE))
        {
            log.fine("Using algorithm " + initParam);
        }
        
        return initParam;
        
    }
    
    private static SecretKey getMacSecret(ExternalContext ctx)
    {
        Object secretKey = (SecretKey) ctx.getApplicationMap().get(INIT_MAC_SECRET_KEY_CACHE);
        
        if (secretKey == null)
        {
            String cache = ctx.getInitParameter(INIT_MAC_SECRET_KEY_CACHE);
            
            if(cache == null)
            {
                cache = ctx.getInitParameter(INIT_MAC_SECRET_KEY_CACHE.toLowerCase());
            }
            
            if ("false".equals(cache))
            {
                // No cache is used. This option is activated
                String secret = ctx.getInitParameter(INIT_MAC_SECRET);
                
                if (secret == null)
                {
                    secret = ctx.getInitParameter(INIT_MAC_SECRET.toLowerCase());
                }
                
                if (secret == null)
                {
                    throw new NullPointerException("Could not find secret using key '" + INIT_MAC_SECRET + '\'');
                }
                
                String macAlgorithm = findMacAlgorithm(ctx);

                secretKey = new SecretKeySpec(findMacSecret(ctx, macAlgorithm), macAlgorithm);
            }
            else
            {
                throw new NullPointerException("Could not find SecretKey in application scope using key '" 
                        + INIT_MAC_SECRET_KEY_CACHE + '\'');
            }
        }
        
        if( ! ( secretKey instanceof SecretKey ) )
        {
            throw new ClassCastException("Did not find an instance of SecretKey "
                    + "in application scope using the key '" + INIT_MAC_SECRET_KEY_CACHE + '\'');
        }

        
        return (SecretKey) secretKey;
    }

    private static byte[] findMacSecret(ExternalContext ctx, String algorithm)
    {
        String secret = ctx.getInitParameter(INIT_MAC_SECRET);
        
        if (secret == null)
        {
            secret = ctx.getInitParameter(INIT_MAC_SECRET.toLowerCase());
        }
 
        return findMacSecret(secret, algorithm);
    }    
    
    private static byte[] findMacSecret(ServletContext ctx, String algorithm)
    {
        String secret = ctx.getInitParameter(INIT_MAC_SECRET);
        
        if (secret == null)
        {
            secret = ctx.getInitParameter(INIT_MAC_SECRET.toLowerCase());
        }
        
        return findMacSecret(secret, algorithm);
    }

    private static byte[] findMacSecret(String secret, String algorithm)
    {
        byte[] bytes = null;
        
        if(secret == null)
        {
            try
            {
                KeyGenerator kg = KeyGenerator.getInstance(algorithm);
                bytes = kg.generateKey().getEncoded();
                
                if(log.isLoggable(Level.FINE))
                {
                    log.fine("generated random mac password of length " + bytes.length);
                }
            }
            catch (NoSuchAlgorithmException e)
            {
                // Generate random password length 8, 
                int length = 8;
                bytes = new byte[length];
                new Random().nextBytes(bytes);
                
                if(log.isLoggable(Level.FINE))
                {
                    log.fine("generated random mac password of length " + length);
                }
            }
        }
        else 
        {
            bytes = decode(secret.getBytes());
        }
        
        return bytes;
    }
}
