/*
 * Tigase Jabber/XMPP Utils
 * Copyright (C) 2004-2007 "Artur Hefczyc" <artur.hefczyc@tigase.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. Look for COPYING file in the top folder.
 * If not, see http://www.gnu.org/licenses/.
 *
 * $Rev$
 * Last modified by $Author$
 * $Date$
 */
package tigase.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * Describe class Algorithms here.
 *
 *
 * Created: Wed May  4 13:24:03 2005
 *
 * @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
 * @version $Rev$
 */
public class Algorithms {

  /**
   * Creates a new <code>Algorithms</code> instance.
   *
   */
  private Algorithms() { }

  /**
   * This method encodes data using digest algorithm described in
   * <em>JEP-0078</em> documentation.
   * As a result you have <code>String</code> containing digest data which
   * can be compared with data sent by the user to authenticate him.
   *
   * @param id a <code>String</code> value of some ID value like session ID to
   * concatenate with secret word.
   * @param secret a <code>String</code> value of a secret word shared between
   * entites.
   * @param alg a <code>String</code> value of algorithm name to use for
   * generating diffest message.
   * @return a <code>String</code> value digest message as defined.
   * @exception NoSuchAlgorithmException if an error occurs during encoding
   * digest message.
   */
  public static final String hexDigest(final String id, final String secret,
    final String alg) throws NoSuchAlgorithmException {
    return bytesToHex(digest(id, secret, alg));
  }

  public static final byte[] digest(final String id, final String secret,
    final String alg) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance(alg);
    String conc = id + secret;
    md.update(conc.getBytes());
    return md.digest();
  }

	public static final String bytesToHex(final byte[] buff) {
    StringBuilder res = new StringBuilder();
    for (byte b : buff) {
      char ch = Character.forDigit((b >> 4) & 0xF, 16);
      res.append(ch);
      ch = Character.forDigit(b & 0xF, 16);
      res.append(ch);
    } // end of for (b : digest)
    return res.toString();
	}

	private static String help() {
		return
			" -id id				id used to calculate digest\n"
			+ " -pass pass			password phrase for digest calculation\n"
			+ " -alg alg			algorith to use for calculating digest\n"
			;
	}

	/**
	 * Describe <code>main</code> method here.
	 *
	 * @param args a <code>String[]</code> value
	 */
	public static void main(final String[] args) throws Exception {
		String id = null;
		String pass = null;
		String alg = "MD5";
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("-h")) {
				System.out.println(help());
				System.exit(0);
			} // end of if (args[i].equals("-id"))
			if (args[i].equals("-id")) {
				id = args[++i];
			} // end of if (args[i].equals("-id"))
			if (args[i].equals("-pass")) {
				pass = args[++i];
			} // end of if (args[i].equals("-id"))
			if (args[i].equals("-alg")) {
				alg = args[++i];
			} // end of if (args[i].equals("-id"))
		} // end of for (int i = 0; i < args.length; i++)
		if (id == null) {
			id = "";
		} // end of if (id == null)
		System.out.println(hexDigest(id, pass, alg));
	}

} // Algorithms
@@ -2160,18 +2160,101 @@
 );%0A  %7D%0A%0A
-  
+%09private final static byte%5B%5D NULL_CHARS_ARRAY = new byte%5B%5D %7B 110, 117, 108, 108 %7D;%0A%0A%09
 public s
@@ -2308,36 +2308,32 @@
 l String secret,
-%0A   
  final String al
@@ -2369,20 +2369,18 @@
 ption %7B%0A
-    
+%09%09
 MessageD
@@ -2426,57 +2426,176 @@
 g);%0A
-    String conc = id + secret;%0A    md.update(conc
+%0A%09%09if (id == null)%0A%09%09%09md.update(NULL_CHARS_ARRAY);%0A%09%09else%0A%09%09%09md.update(id.getBytes());%0A%0A%09%09if (secret == null)%0A%09%09%09md.update(NULL_CHARS_ARRAY);%0A%09%09else%0A%09%09%09md.update(secret
 .get
@@ -2604,20 +2604,19 @@
 tes());%0A
-    
+%0A%09%09
 return m
@@ -2627,18 +2627,17 @@
 gest();%0A
-  
+%09
 %7D%0A%0A%09publ
@@ -3312,16 +3312,17 @@
 ic void 
+$
 main(fin

improve hash calculation performance