/*
 * Copyright  2003-2004 The Apache Software Foundation.
 *
 *  Licensed 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.ws.security.message.token;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.util.DOM2Writer;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.apache.ws.security.util.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.namespace.QName;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.TimeZone;

/**
 * UsernameToken according to WS Security specifications, UsernameToken profile.
 * 
 * @author Davanum Srinivas (dims@yahoo.com)
 * @author Werner Dittmann (Werner.Dittmann@siemens.com)
 */
public class UsernameToken {
    private static Log log = LogFactory.getLog(UsernameToken.class.getName());

    public static final String PASSWORD_TYPE = "passwordType";

    protected Element element = null;

    protected Element elementUsername = null;

    protected Element elementPassword = null;

    protected Element elementNonce = null;

    protected Element elementCreated = null;

    protected Element elementSalt = null;

    protected Element elementIteration = null;

    protected String passwordType = null;

    protected boolean hashed = true;

    private static SecureRandom random = null;

    private static int DEFAULT_ITERATION = 1000;

    public static final QName TOKEN = new QName(WSConstants.WSSE_NS,
            WSConstants.USERNAME_TOKEN_LN);

    static {
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException nsae) {
            nsae.printStackTrace();
        }
    }

    /**
     * Constructs a <code>UsernameToken</code> object and parses the
     * <code>wsse:UsernameToken</code> element to initialize it.
     * 
     * @param elem
     *            the <code>wsse:UsernameToken</code> element that contains
     *            the UsernameToken data
     * @throws WSSecurityException
     */
    public UsernameToken(Element elem) throws WSSecurityException {
        this.element = elem;
        QName el = new QName(this.element.getNamespaceURI(), this.element
                .getLocalName());
        if (!el.equals(TOKEN)) {
            throw new WSSecurityException(
                    WSSecurityException.INVALID_SECURITY_TOKEN,
                    "badTokenType00", new Object[] { el });
        }
        elementUsername = (Element) WSSecurityUtil.getDirectChild(element,
                "Username", WSConstants.WSSE_NS);
        elementPassword = (Element) WSSecurityUtil.getDirectChild(element,
                "Password", WSConstants.WSSE_NS);
        elementNonce = (Element) WSSecurityUtil.getDirectChild(element,
                "Nonce", WSConstants.WSSE_NS);
        elementCreated = (Element) WSSecurityUtil.getDirectChild(element,
                "Created", WSConstants.WSU_NS);
        elementSalt = (Element) WSSecurityUtil.getDirectChild(element, "Salt",
                WSConstants.WSSE11_NS);
        elementIteration = (Element) WSSecurityUtil.getDirectChild(element,
                "Interation", WSConstants.WSSE11_NS);
        if (elementUsername == null) {
            throw new WSSecurityException(
                    WSSecurityException.INVALID_SECURITY_TOKEN,
                    "badTokenType01", new Object[] { el });
        }
        if (elementSalt != null) {
            if (elementPassword != null) {
                throw new WSSecurityException(
                        WSSecurityException.INVALID_SECURITY_TOKEN,
                        "badTokenType01", new Object[] { el });
            }
            return;
        }
        hashed = false;
        if (elementPassword != null) {
            passwordType = elementPassword.getAttribute("Type");
        }
        if (passwordType != null
                && passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
            hashed = true;
            if (elementNonce == null || elementCreated == null) {
                throw new WSSecurityException(
                        WSSecurityException.INVALID_SECURITY_TOKEN,
                        "badTokenType01", new Object[] { el });
            }
        }
    }

    /**
     * Constructs a <code>UsernameToken</code> object according to the defined
     * parameters. <p/> This constructs set the password encoding to
     * {@link WSConstants#PASSWORD_DIGEST}
     * 
     * @param doc
     *            the SOAP envelope as <code>Document</code>
     */
    public UsernameToken(boolean milliseconds, Document doc) {
        this(milliseconds, doc, WSConstants.PASSWORD_DIGEST);
    }

    /**
     * Constructs a <code>UsernameToken</code> object according to the defined
     * parameters. <p/>
     * 
     * @param doc
     *            the SOAP envelope as <code>Document</code>
     * @param pwType
     *            the required password encoding, either
     *            {@link WSConstants#PASSWORD_DIGEST} or
     *            {@link WSConstants#PASSWORD_TEXT} or <code>null</code> if no
     *            password required
     */
    public UsernameToken(boolean milliseconds, Document doc, String pwType) {
        this.element = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
                + WSConstants.USERNAME_TOKEN_LN);
        WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS,
                WSConstants.WSSE_PREFIX);

        this.elementUsername = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
                + WSConstants.USERNAME_LN);
        WSSecurityUtil.setNamespace(this.elementUsername, WSConstants.WSSE_NS,
                WSConstants.WSSE_PREFIX);
        this.elementUsername.appendChild(doc.createTextNode(""));
        element.appendChild(elementUsername);

        if (pwType != null) {
            this.elementPassword = doc.createElementNS(WSConstants.WSSE_NS,
                    "wsse:" + WSConstants.PASSWORD_LN);
            WSSecurityUtil.setNamespace(this.elementPassword,
                    WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
            this.elementPassword.appendChild(doc.createTextNode(""));
            element.appendChild(elementPassword);

            hashed = false;
            passwordType = pwType;
            if (passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
                hashed = true;
                addNonce(doc);
                addCreated(milliseconds, doc);
            }
        }
    }

    /**
     * Creates and adds a Nonce element to this UsernameToken
     */
    public void addNonce(Document doc) {
        if (elementNonce != null) {
            return;
        }
        byte[] nonceValue = new byte[16];
        random.nextBytes(nonceValue);
        this.elementNonce = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
                + WSConstants.NONCE_LN);
        WSSecurityUtil.setNamespace(this.elementNonce, WSConstants.WSSE_NS,
                WSConstants.WSSE_PREFIX);
        this.elementNonce.appendChild(doc.createTextNode(Base64
                .encode(nonceValue)));
        element.appendChild(elementNonce);
    }

    /**
     * Creates and adds a Created element to this UsernameToken
     */
    public void addCreated(boolean milliseconds, Document doc) {
        if (elementCreated != null) {
            return;
        }
        DateFormat zulu = null;
        if (milliseconds) {
            zulu = new XmlSchemaDateFormat();
        } else {
            zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
        }
        Calendar rightNow = Calendar.getInstance();
        this.elementCreated = doc.createElementNS(WSConstants.WSU_NS,
                WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN);
        WSSecurityUtil.setNamespace(this.elementCreated, WSConstants.WSU_NS,
                WSConstants.WSU_PREFIX);
        this.elementCreated.appendChild(doc.createTextNode(zulu.format(rightNow
                .getTime())));
        element.appendChild(elementCreated);
    }

    /**
     * Adds and optionally creates a Salt element to this UsernameToken.
     * 
     * If the <code>saltCalue</code> is <code>null</code> the the method
     * generates a new salt. Otherwise it uses the the given value.
     * 
     * @param doc
     *            The Document for the UsernameToken
     * @param saltValue
     *            The salt to add, if null generate a new salt value
     * @param mac
     *            If <code>true</code> then an optionally generated value is
     *            usable for a MAC
     * @return Returns the added salt
     */
    public byte[] addSalt(Document doc, byte[] saltValue, boolean mac) {

        if (saltValue == null) {
            saltValue = generateSalt(mac);
        }
        this.elementSalt = doc.createElementNS(WSConstants.WSSE11_NS,
                WSConstants.WSSE11_PREFIX + WSConstants.SALT_LN);
        WSSecurityUtil.setNamespace(this.elementSalt, WSConstants.WSSE11_NS,
                WSConstants.WSSE11_PREFIX);
        this.elementSalt.appendChild(doc.createTextNode(Base64
                .encode(saltValue)));
        element.appendChild(elementSalt);
        return saltValue;
    }

    /**
     * Creates and adds a Iteration element to this UsernameToken
     */
    public void addIteration(Document doc, int iteration) {
        String text = "" + iteration;
        this.elementIteration = doc.createElementNS(WSConstants.WSSE11_NS,
                WSConstants.WSSE11_PREFIX + WSConstants.ITERATION_LN);
        WSSecurityUtil.setNamespace(this.elementIteration,
                WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
        this.elementIteration.appendChild(doc.createTextNode(text));
        element.appendChild(elementIteration);
        return;
    }

    /**
     * Get the user name.
     * 
     * @return the data from the user name element.
     */
    public String getName() {
        return nodeString(this.elementUsername);
    }

    /**
     * Set the user name.
     * 
     * @param name
     *            sets a text node containing the use name into the user name
     *            element.
     */
    public void setName(String name) {
        Text node = getFirstNode(this.elementUsername);
        node.setData(name);
    }

    /**
     * Get the nonce.
     * 
     * @return the data from the nonce element.
     */
    public String getNonce() {
        return nodeString(this.elementNonce);
    }

    /**
     * Get the created timestamp.
     * 
     * @return the data from the created time element.
     */
    public String getCreated() {
        return nodeString(this.elementCreated);
    }

    /**
     * Gets the password string. This is the password as it is in the password
     * element of a username, token. Thus it can be either plain text or the
     * password digest value.
     * 
     * @return the password string or <code>null</code> if no such node
     *         exists.
     */
    public String getPassword() {
        return nodeString(this.elementPassword);
    }

    /**
     * Get the Salt value of this UsernameToken.
     * 
     * @return Returns the binary Salt value or <code>null</code> if no Salt
     *         value is available in the username token.
     * @throws WSSecurityException
     */
    public byte[] getSalt() throws WSSecurityException {
        String salt = nodeString(this.elementSalt);
        if (salt != null) {
            return Base64.decode(nodeString(this.elementSalt));
        }
        return null;
    }

    /**
     * Get the Iteration value of this UsernameToken.
     * 
     * @return Returns the Iteration value. If no Iteration was specified in the
     *         username token the default value according to the specification
     *         is returned.
     */
    public int getIteration() {
        String iter = nodeString(this.elementIteration);
        if (iter != null) {
            return Integer.parseInt(iter);
        }
        return DEFAULT_ITERATION;
    }

    /**
     * Get the hashed indicator. If the indicator is
     * <code>true> the password of the
     * <code>UsernameToken</code> was encoded using
     * {@link WSConstants#PASSWORD_DIGEST}
     *
     * @return the hashed indicator.
     */
    public boolean isHashed() {
        return hashed;
    }

    /**
     * @return Returns the passwordType.
     */
    public String getPasswordType() {
        return passwordType;
    }

    /**
     * Sets the password string. This function sets the password in the
     * <code>UsernameToken</code> either as plain text or encodes the password
     * according to the WS Security specifications, UsernameToken profile, into
     * a password digest.
     * 
     * @param pwd
     *            the password to use
     */
    public void setPassword(String pwd) {
        if (pwd == null) {
            throw new IllegalArgumentException("pwd == null");
        }
        Text node = getFirstNode(this.elementPassword);
        try {
            if (!hashed) {
                node.setData(pwd);
                this.elementPassword.setAttribute("Type",
                        WSConstants.PASSWORD_TEXT);
            } else {
                node.setData(doPasswordDigest(getNonce(), getCreated(), pwd));
                this.elementPassword.setAttribute("Type",
                        WSConstants.PASSWORD_DIGEST);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String doPasswordDigest(String nonce, String created,
            String password) {
        String passwdDigest = null;
        try {
            byte[] b1 = Base64.decode(nonce);
            byte[] b2 = created.getBytes("UTF-8");
            byte[] b3 = password.getBytes("UTF-8");
            byte[] b4 = new byte[b1.length + b2.length + b3.length];
            int i = 0;
            int offset = 0;
            System.arraycopy(b1, 0, b4, offset, b1.length);
            offset += b1.length;
            
            System.arraycopy(b2, 0, b4, offset, b2.length);
            offset += b2.length;

            System.arraycopy(b3, 0, b4, offset, b3.length);
            
            MessageDigest sha = MessageDigest.getInstance("SHA-1");
            sha.reset();
            sha.update(b4);
            passwdDigest = Base64.encode(sha.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return passwdDigest;
    }

    /**
     * Returns the first text node of an element.
     * 
     * @param e
     *            the element to get the node from
     * @return the first text node or <code>null</code> if node is null or is
     *         not a text node
     */
    private Text getFirstNode(Element e) {
        Node node = e.getFirstChild();
        return ((node != null) && node instanceof Text) ? (Text) node : null;
    }

    /**
     * Returns the data of an element as String or null if either the the element
     * does not contain a Text node or the node is empty.
     * 
     * @param e
     *            DOM element
     * @return Element text node data as String
     */
    private String nodeString(Element e) {
        if (e != null) {
            Text node = getFirstNode(e);
            if (node != null) {
                return node.getData();
            }
        }
        return null;

    }

    /**
     * Returns the dom element of this <code>UsernameToken</code> object.
     * 
     * @return the <code>wsse:UsernameToken</code> element
     */
    public Element getElement() {
        return this.element;
    }

    /**
     * Returns the string representation of the token.
     * 
     * @return a XML string representation
     */
    public String toString() {
        return DOM2Writer.nodeToString((Node) this.element);
    }

    /**
     * Gets the id.
     * 
     * @return the value of the <code>wsu:Id</code> attribute of this username
     *         token
     */
    public String getID() {
        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
    }

    /**
     * Set the id of this username token.
     * 
     * @param id
     *            the value for the <code>wsu:Id</code> attribute of this
     *            username token
     */
    public void setID(String id) {
        String prefix = WSSecurityUtil.setNamespace(this.element,
                WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
    }

    /**
     * Gets the secret key as per WS-Trust spec. This method uses default setting
     * to generate the secret key. These default values are suitable for .NET
     * WSE.
     * 
     * @return a secret key constructed from information contained in this
     *         username token
     */
    public byte[] getSecretKey() {
        return getSecretKey(WSConstants.WSE_DERIVED_KEY_LEN,
                WSConstants.LABEL_FOR_DERIVED_KEY);
    }

    /**
     * Gets the secret key as per WS-Trust spec.
     * 
     * @param keylen
     *            How many bytes to generate for the key
     * @param labelString
     *            the label used to generate the seed
     * @return a secret key constructed from information contained in this
     *         username token
     */
    public byte[] getSecretKey(int keylen, String labelString) {
        byte[] key = null;
        try {
            Mac mac = Mac.getInstance("HMACSHA1");
            byte[] password = getPassword().getBytes("UTF-8");
            byte[] label = labelString.getBytes("UTF-8");
            byte[] nonce = Base64.decode(getNonce());
            byte[] created = getCreated().getBytes("UTF-8");
            byte[] seed = new byte[label.length + nonce.length + created.length];

            int offset = 0;
            System.arraycopy(label, 0, seed, offset, label.length);
            offset += label.length;
            
            System.arraycopy(nonce, 0, seed, offset, nonce.length);
            offset += nonce.length;

            System.arraycopy(created, 0, seed, offset, created.length);
            
            key = P_hash(password, seed, mac, keylen);

            if (log.isDebugEnabled()) {
                log.debug("password   :" + Base64.encode(password));
                log.debug("label      :" + Base64.encode(label));
                log.debug("nonce      :" + Base64.encode(nonce));
                log.debug("created    :" + Base64.encode(created));
                log.debug("seed       :" + Base64.encode(seed));
                log.debug("Key        :" + Base64.encode(key));
            }
        } catch (Exception e) {
            return null;
        }
        return key;
    }

    /**
     * This static method generates a derived key as defined in WSS Username
     * Token Profile.
     * 
     * @param password
     *            The password to include in the key generation
     * @param salt
     *            The Salt value
     * @param iteration
     *            The Iteration value. If zero (0) is given the method uses the
     *            default value
     * @return Returns the derived key a byte array
     * @throws WSSecurityException
     */
    public static byte[] generateDerivedKey(String password, byte[] salt,
            int iteration) throws WSSecurityException {

        if (iteration == 0) {
            iteration = DEFAULT_ITERATION;
        }
        byte[] pwBytes = password.getBytes();

        byte[] pwSalt = new byte[salt.length + pwBytes.length];
        System.arraycopy(pwBytes, 0, pwSalt, 0, pwBytes.length);
        System.arraycopy(salt, 0, pwSalt, pwBytes.length, salt.length);

        MessageDigest sha = null;
        try {
            sha = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e) {
            throw new WSSecurityException(0, "noSHA1availabe");
        }
        sha.reset();

        /*
         * Make the first hash round with start value
         */
        byte[] K = sha.digest(pwSalt);
        /*
         * Perform the 2nd up to iteration hash rounds
         */
        for (int i = 2; i <= iteration; i++) {
            sha.reset();
            K = sha.digest(K);
        }
        return K;
    }

    /**
     * This static method generates a 128 bit salt value as defined in WSS
     * Username Token Profile.
     * 
     * @param useForMac
     *            If <code>true</code> define the Salt for use in a MAC
     * @return Returns the 128 bit salt value as byte array
     */
    public static byte[] generateSalt(boolean useForMac) {
        byte[] saltValue = new byte[16];
        random.nextBytes(saltValue);
        if (useForMac) {
            saltValue[15] = 0x01;
        } else {
            saltValue[15] = 0x02;
        }
        return saltValue;
    }

    /**
     * P_hash as defined in RFC 2246 for TLS.
     * 
     * @param secret
     *            is the key for the HMAC
     * @param seed
     *            the seed value to start the generation - A(0)
     * @param mac
     *            the HMAC algorithm
     * @param required
     *            number of bytes to generate
     * @return a byte array that contains a secret key
     * @throws Exception
     */
    private static byte[] P_hash(byte[] secret, byte[] seed, Mac mac,
            int required) throws Exception {
        byte[] out = new byte[required];
        int offset = 0, tocpy;
        byte[] A, tmp;
        /*
         * A(0) is the seed
         */
        A = seed;
        SecretKeySpec key = new SecretKeySpec(secret, "HMACSHA1");
        mac.init(key);
        while (required > 0) {
            mac.update(A);
            A = mac.doFinal();
            mac.update(A);
            mac.update(seed);
            tmp = mac.doFinal();
            tocpy = min(required, tmp.length);
            System.arraycopy(tmp, 0, out, offset, tocpy);
            offset += tocpy;
            required -= tocpy;
        }
        return out;
    }

    /*
     * public static void main(String[] args) throws Exception { byte[] secret =
     * Base64.decode("A4BKgeqUKi9VDwWyYPDrskwCwEQ5RIqH"); byte[] seed =
     * Base64.decode("bWFzdGVyIHNlY3JldAAAAAAAAAAAAAAAAAAAAAAy+BE8DDEUf+XnAynZEVU0PUQR4QHesAbNCmt8/Ry6NqBELuBAiZV4Z0FuCT58Fi8=");
     * int required = 48; Mac mac = Mac.getInstance("HMACSHA1"); byte[] out =
     * UsernameToken.P_hash(secret, seed, mac, 48);
     * System.out.println(Base64.encode(out));
     * //UCbz0pT2DxRfx4IpY6iWRE0KCa4Fg9JKNRlrxE8AtjNjb1NEK17NI6XdrMRMOKM2 }
     */

    /**
     * helper method.
     * <p/>
     *
     * @param a
     * @param b
     * @return
     */
    private static int min(int a, int b) {
        return (a > b) ? b : a;
    }
}
