package org.hive2hive.core.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;

import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.io.DigestInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Util for hashing and comparing hashes.
 * 
 * @author Nico, Chris
 * 
 */
public class HashUtil {

	private static final Logger logger = LoggerFactory.getLogger(HashUtil.class);

	private HashUtil() {
		// only static methods
	}

	/**
	 * Generates a MD5 hash of a given data
	 * 
	 * @param data to calculate the MD5 hash over it
	 * @return the md5 hash
	 */
	public static byte[] hash(byte[] data) {
		MD5Digest digest = new MD5Digest();
		digest.update(data, 0, data.length);
		byte[] md5 = new byte[digest.getDigestSize()];
		digest.doFinal(md5, 0);
		return md5;
	}

	/**
	 * Generates a MD5 hash of an input stream (can take a while)
	 * 
	 * @param file
	 * @return the hash of the file
	 * @throws IOException
	 */
	public static byte[] hash(File file) throws IOException {
		if (file == null) {
			return new byte[0];
		} else if (file.isDirectory()) {
			return new byte[0];
		} else if (!file.exists()) {
			return new byte[0];
		}

		byte[] buffer = new byte[1024];
		int numRead;
		FileInputStream fis;

		try {
			// open the stream
			fis = new FileInputStream(file);
		} catch (FileNotFoundException e) {
			logger.error("File {} not found to generate the hash", file, e);
			return new byte[0];
		}

		MD5Digest digest = new MD5Digest();
		DigestInputStream dis = new DigestInputStream(fis, digest);
		do {
			numRead = dis.read(buffer);
			if (numRead > 0) {
				digest.update(buffer, 0, numRead);
			}
		} while (numRead != -1);
		dis.close();
		fis.close();

		byte[] md5 = new byte[digest.getDigestSize()];
		digest.doFinal(md5, 0);

		return md5;
	}

	/**
	 * Compares if the file md5 matches a given md5 hash
	 * 
	 * @param file
	 * @param expectedMD5
	 * @return <code>true</code> if the file has the expected hash
	 * @throws IOException
	 */
	public static boolean compare(File file, byte[] expectedMD5) throws IOException {
		if (!file.exists() && (expectedMD5 == null || expectedMD5.length == 0)) {
			// both do not exist
			return true;
		} else if (file.isDirectory()) {
			// directories always match
			return true;
		}

		byte[] md5Hash = HashUtil.hash(file);
		return compare(md5Hash, expectedMD5);
	}

	/**
	 * Compares if the given md5 matches another md5 hash. This method works symmetrically and is not
	 * dependent on the parameter order
	 * 
	 * @param md5 the hash to test
	 * @param expectedMD5 the expected md5 hash
	 * @return <code>true</code> if the hashes match
	 */
	public static boolean compare(byte[] md5, byte[] expectedMD5) {
		return Arrays.equals(md5, expectedMD5);
	}
}

@@ -166,124 +166,144 @@
 ava.
-util.Arrays;%0A%0Aimport org.bouncycastle.crypto.digests.MD5Digest;%0Aimport org.bouncycastle.crypto.io.DigestInputStream;
+security.DigestInputStream;%0Aimport java.security.MessageDigest;%0Aimport java.security.NoSuchAlgorithmException;%0Aimport java.util.Arrays;%0A
 %0Aimp
@@ -403,16 +403,102 @@
 hashes.%0A
+ * TODO: this could be parameterized with the security provider for an optimal result%0A
  * %0A * @
@@ -508,17 +508,27 @@
 hor Nico
-,
+%0A * @author
  Chris%0A 
@@ -637,16 +637,69 @@
 .class);
+%0A%09private static final String HASH_ALGORITHM = %22MD5%22;
 %0A%0A%09priva
@@ -922,44 +922,84 @@
 %7B%0A%09%09
-MD5Digest digest = new MD5Digest(
+try %7B%0A%09%09%09MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM
 );%0A
+%09
 %09%09di
@@ -1039,94 +1039,165 @@
 ;%0A%09%09
-byte%5B%5D md5 = new byte%5Bdigest.getDigestSize()%5D;%0A%09%09digest.doFinal(md5, 0
+%09return digest.digest();%0A%09%09%7D catch (NoSuchAlgorithmException e) %7B%0A%09%09%09logger.error(%22Invalid hash algorithm %7B%7D%22, HASH_ALGORITHM, e
 );%0A%09%09
+%09
 return 
-md5;
+new byte%5B0%5D;%0A%09%09%7D
 %0A%09%7D%0A
@@ -1565,24 +1565,245 @@
 te%5B0%5D;%0A%09%09%7D%0A%0A
+%09%09MessageDigest digest;%0A%09%09try %7B%0A%09%09%09digest = MessageDigest.getInstance(HASH_ALGORITHM);%0A%09%09%7D catch (NoSuchAlgorithmException e) %7B%0A%09%09%09logger.error(%22Invalid hash algorithm %7B%7D%22, HASH_ALGORITHM, e);%0A%09%09%09return new byte%5B0%5D;%0A%09%09%7D%0A%0A
 %09%09byte%5B%5D buf
@@ -2067,46 +2067,8 @@
 %09%7D%0A%0A
-%09%09MD5Digest digest = new MD5Digest();%0A
 %09%09Di
@@ -2293,94 +2293,30 @@
 %0A%0A%09%09
-byte%5B%5D md5 = new byte%5Bdigest.getDigestSize()%5D;%0A%09%09digest.doFinal(md5, 0);%0A%0A%09%09return md5
+return digest.digest()
 ;%0A%09%7D

Remove BC dependency from HashUtil