/**
* Copyright (c) 2009--2016 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.common.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Copied from: http://www.koders.com/java/fidEC98D99B347D738A2B560EA856B93ADEABCF6B4E.aspx
* @version $Rev$
*/
public class MD5Sum {
// limit for byte array in memory - 2,147,483,647 bytes OR 2.1GB
public static final int SCOUR_MD5_BYTE_LIMIT = Integer.MAX_VALUE;
// buffer size to read file by chunks - 4 MB
public static final int MD5_BUFFER_SIZE = 1024 * 1024 * 4;
private static MessageDigest md = null;
private MD5Sum() {
}
/**
* Method: md5Sum Purpose: calculate the MD5 in a way compatible with how
* the scour.net protocol encodes its passwords (incidentally, it also
* outputs a string identical to the md5sum unix command).
* @param str the String from which to calculate the sum
* @return the MD5 checksum
*/
public static String md5Sum(String str) {
try {
return md5Sum(str.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e.getMessage());
}
}
/**
* MD5Sum the byte array
*
* @param input to sum
* @return String md5sum
*/
public static String md5Sum(byte[] input) {
return md5Sum(input, -1);
}
/**
* mdsum the byte array with a limit
* @param input to sum
* @param limit to stop at
* @return String md5sum
*/
public static String md5Sum(byte[] input, int limit) {
try {
if (md == null) {
md = MessageDigest.getInstance("MD5");
}
md.reset();
byte[] digest;
if (limit == -1) {
digest = md.digest(input);
}
else {
md.update(input, 0, limit > input.length ? input.length : limit);
digest = md.digest();
}
StringBuilder hexString = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
hexString.append(hexDigit(digest[i]));
}
return hexString.toString();
}
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e.getMessage());
}
}
/**
* Method: hexDigit Purpose: convert a hex digit to a String, used by
* md5Sum.
* @param x the digit to translate
* @return the hex code for the digit
*/
private static String hexDigit(byte x) {
StringBuilder sb = new StringBuilder();
char c;
// First nibble
c = (char) ((x >> 4) & 0xf);
if (c > 9) {
c = (char) ((c - 10) + 'a');
}
else {
c = (char) (c + '0');
}
sb.append(c);
// Second nibble
c = (char) (x & 0xf);
if (c > 9) {
c = (char) ((c - 10) + 'a');
}
else {
c = (char) (c + '0');
}
sb.append(c);
return sb.toString();
}
/**
* Method: getFileMD5Sum Purpose: get the MD5 sum of a file.
* @param f the file to read
* @return the MD5 sum string
* @throws IOException on IO error
* @throws MD5CryptException on getting MD5 MessageDigest instance
*/
public static String getFileMD5Sum(File f) throws IOException, MD5CryptException {
try {
if (md == null) {
md = MessageDigest.getInstance("MD5");
}
}
catch (NoSuchAlgorithmException e) {
throw new MD5CryptException(
"Problem getting MD5 message digest " + "(NoSuchAlgorithm Exception).");
}
md.reset();
FileInputStream fis = new FileInputStream(f);
byte[] dataBuffer = new byte[MD5_BUFFER_SIZE];
int nread = 0;
while ((nread = fis.read(dataBuffer)) != -1) {
md.update(dataBuffer, 0, nread);
}
fis.close();
byte[] digest = md.digest();
StringBuilder hexString = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
hexString.append(hexDigit(digest[i]));
}
return hexString.toString();
}
}