MD5 utilities





9
Date Submitted Thu. Mar. 2nd, 2006 2:08 AM
Revision 1 of 1
Beginner depsypher
Tags Java
Comments 0 comments
A utility class that gets the MD5 hash of an input stream. Also includes a method for converting byte array to hex-formatted string.

import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileUtils
{
    static final int MD5_BUFFER_SIZE = 1024 * 16;

    /**
     * Get the MD5 hash of the given input stream.
     *
     * @param ins The input stream to read from
     * @return Returns the MD5 hash for the given input stream
     */

    public static byte[] getMD5Hash(InputStream ins) throws IOException
    {
        return getMD5Hash(ins, 0, 0);
    }

    /**
     * Get the MD5 hash of the contents of the given input stream starting at
     * the given offset and going until length bytes are read
     *
     * @param ins The input stream to pull bytes from
     * @param offset How far from the beginning to start
     * @param length Number of bytes to read. If zero or smaller read to the end
     * @return Returns a byte array containing 16 bytes corresponding to the MD5
     *         hash code for the input.
     */

    public static byte[] getMD5Hash(InputStream ins, long offset, long length)
        throws IOException
    {
        if(ins == null) {
            throw new IllegalArgumentException("ins should not be null");
        }
        if(offset < 0) {
            throw new IllegalArgumentException("offset should not be negative");
        }

        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        }
        catch(NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        ins.skip(offset);
        int bytesRead = 0;

        // if length is positive read length number of bytes, otherwise read
        // until the end
        if(length > 0)
        {
            byte[] bytes = new byte[(int)length];
            bytesRead = ins.read(bytes);
            if(bytesRead < length)
            {
                byte[] lastBytes = new byte[bytesRead];
                System.arraycopy(bytes, 0, lastBytes, 0, lastBytes.length);
                md.update(lastBytes);
                return md.digest();
            }
            md.update(bytes);
        }
        else
        {
            byte[] bytes = new byte[MD5_BUFFER_SIZE];
            while(bytesRead > -1)
            {
                bytesRead = ins.read(bytes);

                if(bytesRead < MD5_BUFFER_SIZE)
                {
                    byte[] lastBytes = new byte[bytesRead];
                    System.arraycopy(bytes, 0, lastBytes, 0, lastBytes.length);
                    md.update(lastBytes);
                    return md.digest();
                }
                else {
                    md.update(bytes);
                }
            }
        }

        return md.digest();
    }

    /**
     * Get a String representation of the byte array in hex format
     *
     * @param data The byte array containing the data to convert
     * @return Returns a string representation of the byte array in hex format
     */

    public static String toHexString(byte[] data)
    {
        return toHexString(data, 0, -1);
    }

    /**
     * Get a String representation of the byte array in hex format
     *
     * @param data The byte array containing the data to convert
     * @param offset How far from the beginning to start
     * @param length Number of bytes to read; if negative, reads to the end
     * @return Returns a string representation of the byte array in hex format
     */

    public static String toHexString(byte[] data, int offset, int length)
    {
        if(offset < 0 || offset > data.length) {
            throw new IllegalArgumentException("offset outside of valid range");
        }
        if(length > (data.length - offset)) {
            throw new IllegalArgumentException("invalid length");
        }

        int i = 0;
        int len = (length < 0) ? data.length - offset : length;
        char[] ch = new char[len * 2];
        while(len-- > 0)
        {
            // convert the next byte into a hex digit pair
            //
            int b = data[offset++] & 0xff;
            int d = b >> 4;

            d = (d < 0xA) ? d + '0' : d - 0xA + 'a';
            ch[i++] = (char)d;

            d = b & 0xF;
            d = (d < 0xA) ? d + '0' : d - 0xA + 'a';
            ch[i++] = (char)d;
        }

        return new String(ch);
    }
}
 

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import junit.framework.TestCase;

public class FileUtilsTest extends TestCase
{
    public void testGetMD5HashInputStream() throws Exception
    {
        byte[] data = new byte[] { 0x61, 0x62, 0x63, 0x0a };
        InputStream ins = new ByteArrayInputStream(data);
        assertEquals("0bee89b07a248e27c83fc3d5951213c1", FileUtils.toHexString(FileUtils.getMD5Hash(ins)));
       
        try {
            FileUtils.getMD5Hash(null);
            fail("should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e) {
            // expected exception
        }
    }
    public void testGetMD5HashInputStreamLongLong() throws Exception
    {
        byte[] data = new byte[] { 0x61, 0x62, 0x63, 0x0a };
        InputStream ins = new ByteArrayInputStream(data);
        assertEquals("0bee89b07a248e27c83fc3d5951213c1", FileUtils.toHexString(FileUtils.getMD5Hash(ins, 0, 4)));
               
        ins = new ByteArrayInputStream(data);
        assertEquals("0bee89b07a248e27c83fc3d5951213c1", FileUtils.toHexString(FileUtils.getMD5Hash(ins, 0, 0)));

        ins = new ByteArrayInputStream(data);
        assertEquals("0bee89b07a248e27c83fc3d5951213c1", FileUtils.toHexString(FileUtils.getMD5Hash(ins, 0, -1)));

        ins = new ByteArrayInputStream(data);
        assertEquals("b79898bb7907648871745cd5422c79ce", FileUtils.toHexString(FileUtils.getMD5Hash(ins, 1, -1)));

        ins = new ByteArrayInputStream(data);
        assertEquals("b79898bb7907648871745cd5422c79ce", FileUtils.toHexString(FileUtils.getMD5Hash(ins, 1, 3)));
       
        try {
            FileUtils.getMD5Hash(ins, Integer.MIN_VALUE, 0);
            fail("should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e) {
            // expected exception
        }
       
        try {
            FileUtils.getMD5Hash(null, 0, 0);
            fail("should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e) {
            // expected exception
        }
    }
   
    public void testToHexString()
    {
        byte[] data = "abc\n".getBytes();
        assertEquals("6162630a", FileUtils.toHexString(data, 0, -1));
        assertEquals("62630a", FileUtils.toHexString(data, 1, -1));
        assertEquals("6263", FileUtils.toHexString(data, 1, 2));
        assertEquals("", FileUtils.toHexString(data, 0, 0));
        assertEquals("", FileUtils.toHexString(data, 2, 0));
       
        try {
            FileUtils.toHexString(data, Integer.MAX_VALUE, 0);
            fail("should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e) {
            // expected exception
        }
       
        try {
            FileUtils.toHexString(data, Integer.MIN_VALUE, 0);
            fail("should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e) {
            // expected exception
        }
       
        try {
            FileUtils.toHexString(data, 0, Integer.MAX_VALUE);
            fail("should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e) {
            // expected exception
        }
    }
}
 

Ray V

Comments

There are currently no comments for this snippet.

Voting