/*
* Copyright 2011 Eric F. Savage, code@efsavage.com
*
* 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 com.ajah.util.data;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;
import com.ajah.util.AjahUtils;
/**
* @author <a href="http://efsavage.com">Eric F. Savage</a>,
* <a href="mailto:code@efsavage.com">code@efsavage.com</a>.
*
*/
public class HashUtils {
/**
* Calls {@link #getHashedFileName(String, int, int)} with depth of 3 and
* breadth of 2, which should provide enough separation for most
* applications.
*
* @param name
* The name to hash.
* @return The hashed name with directory path.
*/
public static String getHashedFileName(final String name) {
return getHashedFileName(name, 3, 2);
}
/**
* Creates a hashed name with directory path for a given name.
*
* Example: abcdefghijklmnop with depth of 3 and breadth of 2 would return
* "ab/cd/ef/abcdefghijklmnop". Example: abcdefghijklmnop with depth of 2
* and breadth of 5 would return "abcde/efghi/abcdefghijklmnop".
*
* @param name
* The name to hash.
* @param depth
* The number of subdirectories to split. A higher number will
* yield more directories but fewer files within each directory.
* @param breadth
* The number of characters to use when creating the
* subdirectories. A higher number will yield fewer directories
* but more files within each directory.
* @return The hashed name with directory path.
*/
public static String getHashedFileName(final String name, final int depth, final int breadth) {
AjahUtils.requireParam(name, "name");
final StringBuilder hashed = new StringBuilder();
for (int i = 0; i < depth; i++) {
hashed.append(name.substring(i * breadth, (i + 1) * breadth));
hashed.append("/");
}
hashed.append(name);
return hashed.toString();
}
/**
* Creates an MD5 digest of byte array and returns it as a Base 64 encoded
* number.
*
* @param bytes
* The bytes to digest.
* @return The hexadecimal result of the digest.
*/
public static String md5Base64(final byte[] bytes) {
AjahUtils.requireParam(bytes, "bytes");
try {
final MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = new byte[32];
md.update(bytes, 0, bytes.length);
digest = md.digest();
return DatatypeConverter.printBase64Binary(digest);
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates an MD5 digest of string and returns it as a Base 64 encoded
* number.
*
* @param string
* The string to digest.
* @return The hexadecimal result of the digest.
*/
public static String md5Base64(final String string) {
AjahUtils.requireParam(string, "string");
try {
final MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = new byte[32];
md.update(string.getBytes("iso-8859-1"), 0, string.length());
bytes = md.digest();
return DatatypeConverter.printBase64Binary(bytes);
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates an MD5 digest of string and returns it as a hexadecimal number.
*
* @param string
* The string to digest.
* @return The hexadecimal result of the digest.
*/
public static String md5Hex(final String string) {
AjahUtils.requireParam(string, "string");
try {
final MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = new byte[32];
md.update(string.getBytes("iso-8859-1"), 0, string.length());
bytes = md.digest();
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates an MD5 digest of string and returns it as a hexadecimal number.
*
* @param string
* The string to digest.
* @return The hexadecimal result of the digest.
*/
public static String md5Hex(final byte[] data) {
AjahUtils.requireParam(data, "data");
try {
final MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data, 0, data.length);
final byte[] bytes = md.digest();
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates a SHA-1 digest of byte array and returns it as a hexadecimal
* number.
*
* @param data
* The data to digest.
* @return The hexadecimal result of the digest.
*/
public static String sha1Hex(final byte[] data) {
AjahUtils.requireParam(data, "data");
try {
final MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(data, 0, data.length);
final byte[] bytes = md.digest();
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates a SHA-1 digest of string and returns it as a hexadecimal number.
*
* @param string
* The string to digest.
* @return The hexadecimal result of the digest.
*/
public static String sha1Hex(final String string) {
AjahUtils.requireParam(string, "string");
try {
final MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(string.getBytes("iso-8859-1"), 0, string.length());
final byte[] bytes = md.digest();
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates a SHA-256 digest of string and returns it as a hexadecimal
* number.
*
* @param string
* The string to digest.
* @return The hexadecimal result of the digest.
*/
public static byte[] sha256(final String string) {
AjahUtils.requireParam(string, "string");
try {
final MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(string.getBytes("iso-8859-1"), 0, string.length());
return md.digest();
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
/**
* Creates a SHA-256 digest of string and returns it as a hexadecimal
* number.
*
* @param string
* The string to digest.
* @return The hexadecimal result of the digest.
*/
public static String sha256Hex(final String string) {
final byte[] bytes = sha256(string);
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
}
}