Here is the code for the two classes, owned by Sun Microsystems:

1. class MD5.java
/*
 * @(#)MD5.java 1.9 95/08/07
 *
 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * Updated to the JDK 1.0.2 release by Chuck McManis
 */

package util.crypt;

import java.util.*;

/**
 * The MD5 class is used to compute an MD5 message digest over a given
 * buffer of bytes. It is an implementation of the RSA Data Security Inc
 * MD5 algorithim as described in internet RFC 1321.
 * @version     06 Oct 1996, 1.9.1
 * @author      Chuck McManis
 */
public final class MD5 extends MessageDigest {
    /** containss the computed message digest */

    private int state[];
    private long count;
    private byte buffer[];
    private static int transformBuffer[];

    private static final int S11 = 7;
    private static final int S12 = 12;
    private static final int S13 = 17;
    private static final int S14 = 22;
    private static final int S21 = 5;
    private static final int S22 = 9;
    private static final int S23 = 14;
    private static final int S24 = 20;
    private static final int S31 = 4;
    private static final int S32 = 11;
    private static final int S33 = 16;
    private static final int S34 = 23;
    private static final int S41 = 6;
    private static final int S42 = 10;
    private static final int S43 = 15;
    private static final int S44 = 21;

    /**
     * Standard constructor, creates a new MD5 instance, allocates its
     * buffers from the heap.
     */
    public MD5() {
        state = new int[4];
        count = 0;
        if (transformBuffer == null)
            transformBuffer = new int[16];
        buffer = new byte[64];
        digestBits = new byte[16];
        digestValid = false;
    }

    /**
     * Alternate constructor, allows you to pass in the buffer where you
     * want the resulting digest stored.
     */
    public MD5(byte mydigest[]) {
        state = new int[4];
        count = 0;
        if (transformBuffer == null)
            transformBuffer = new int[16];
        buffer = new byte[64];
        digestBits = mydigest;
        digestValid = false;
    }

    /* **********************************************************
     * The MD5 Functions. These are copied verbatim from
     * the RFC to insure accuracy. The results of this
     * implementation were checked against the RSADSI version.
     * **********************************************************
     */

    private int F(int x, int y, int z) {
        return ((x & y) | ((~x) & z));
    }

    private int G(int x, int y, int z) {
        return ((x & z) | (y & (~z)));
    }

    private int H(int x, int y, int z) {
        return ((x ^ y) ^ z);
    }

    private int I(int x, int y, int z) {
        return (y ^ (x | (~z)));
    }

    private int rotateLeft(int a, int n) {
        return ((a << n) | (a >>> (32 - n)));
    }

    private int FF(int a, int b, int c, int d, int x, int s, int ac) {
        a += F(b, c, d) + x + ac;
        a = rotateLeft(a, s);
        a += b;
        return a;
    }

    private int GG(int a, int b, int c, int d, int x, int s, int ac) {
        a += G(b, c, d) + x + ac;
        a = rotateLeft(a, s);
        a += b;
        return a;
    }

    private int HH(int a, int b, int c, int d, int x, int s, int ac) {
        a += H(b, c, d) + x + ac;
        a = rotateLeft(a, s);
        a += b;
        return a;
    }

    private int II(int a, int b, int c, int d, int x, int s, int ac) {
        a += I(b, c, d) + x + ac;
        a = rotateLeft(a, s);
        a += b;
        return a;
    }

    /**
     * This is where the functions come together as the generic MD5
     * transformation operation, it is called by update() which is
     * synchronized (to protect transformBuffer)
     */
    void transform(byte buf[], int offset) {
        int a, b, c, d;
        int x[] = transformBuffer;

        a = state[0];
        b = state[1];
        c = state[2];
        d = state[3];

        for (int i = 0; i < 16; i++) {
            x[i] = (int)buf[i*4+offset] & 0xff;
            for (int j = 1; j < 4; j++) {
                x[i] += ((int)buf[i*4+j+offset] & 0xff) << (j * 8);
            }
        }

        /* Round 1 */
        a = FF ( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
        d = FF ( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
        c = FF ( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
        b = FF ( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
        a = FF ( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
        d = FF ( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
        c = FF ( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
        b = FF ( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
        a = FF ( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
        d = FF ( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
        c = FF ( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
        b = FF ( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
        a = FF ( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
        d = FF ( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
        c = FF ( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
        b = FF ( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

        /* Round 2 */
        a = GG ( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
        d = GG ( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
        c = GG ( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
        b = GG ( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
        a = GG ( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
        d = GG ( d, a, b, c, x[10], S22,  0x2441453); /* 22 */
        c = GG ( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
        b = GG ( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
        a = GG ( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
        d = GG ( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
        c = GG ( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
        b = GG ( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
        a = GG ( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
        d = GG ( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
        c = GG ( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
        b = GG ( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

        /* Round 3 */
        a = HH ( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
        d = HH ( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
        c = HH ( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
        b = HH ( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
        a = HH ( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
        d = HH ( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
        c = HH ( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
        b = HH ( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
        a = HH ( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
        d = HH ( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
        c = HH ( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
        b = HH ( b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
        a = HH ( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
        d = HH ( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
        c = HH ( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
        b = HH ( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

        /* Round 4 */
        a = II ( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
        d = II ( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
        c = II ( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
        b = II ( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
        a = II ( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
        d = II ( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
        c = II ( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
        b = II ( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
        a = II ( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
        d = II ( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
        c = II ( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
        b = II ( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
        a = II ( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
        d = II ( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
        c = II ( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
        b = II ( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

        state[0] += a;
        state[1] += b;
        state[2] += c;
        state[3] += d;
    }

    /**
     * Initialize the MD5 state information and reset the bit count
     * to 0. Given this implementation you are constrained to counting
     * 2^64 bits.
     */
    public void init() {
        count = 0;
        // Load magic initialization constants.
        state[0] = 0x67452301;
        state[1] = 0xefcdab89;
        state[2] = 0x98badcfe;
        state[3] = 0x10325476;
        digestValid = false;
        for (int i = 0; i < digestBits.length; i++)
            digestBits[i] = 0;
    }

    /**
     * update adds the passed type to the input buffer
     */
    public synchronized void update(byte b) {
        int     index;

        index = (int) ((count >>> 3) & 0x3f);
        count += 8;
        buffer[index] = b;
        if (index  >= 63) {
            transform(buffer, 0);
        }
    }

    /**
     * Perform the final computations, any buffered bytes are added
     * to the digest, the count is added to the digest, and the resulting
     * digest is stored. After calling final you will need to call
     * init() again to do another digest.
     */
    public void finish() {
        byte    bits[] = new byte[8];
        byte    padding[];
        int     i, index, padLen;

        for (i = 0; i < 8; i++) {
            bits[i] = (byte)((count >>> (i * 8)) & 0xff);
        }

        index = (int)(count >> 3) & 0x3f;
        padLen = (index < 56) ? (56 - index) : (120 - index);
        padding = new byte[padLen];
        padding[0] = (byte) 0x80;
        update(padding);
        update(bits);

        for (i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                digestBits[i*4+j] = (byte)((state[i] >>> (j * 8)) & 0xff);
            }
        }
        digestValid = true;
    }

    public String getAlg() {
        return ("MD5");
    }
}

2. class MessageDigest.java

/*
 * @(#)MessageDigest.java       1.7 95/08/15
 *
 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * Updated to JDK 1.0.2 levels by Chuck McManis
 */


package util.crypt;

import java.util.*;
import java.lang.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;


/**
 * The MessageDigest class defines a general class for computing digest
 * functions. It is defined as an abstract class that is subclassed by
 * message digest algorithms. In this way the PKCS classes can be built
 * to take a MessageDigest object without needing to know what 'kind'
 * of message digest they are computing.
 *
 * This class defines the standard functions that all message digest
 * algorithms share, and ways to put all Java fundamental types into
 * the digest. It does not define methods for digestifying either
 * arbitrary objects or arrays of objects however.
 *
 * @version     5 Oct 1996, 1.8
 * @author      Chuck McManis
 */
public abstract class MessageDigest {

    /** the actual digest bits. */
    public byte digestBits[];

    /** status of the digest */
    public boolean digestValid;

    /**
     * This function is used to initialize any internal digest
     * variables or parameters.
     */
    public abstract void init();

    /**
     * The basic unit of digestifying is the byte. This method is
     * defined by the particular algorithim's subclass for that
     * algorithim. Subsequent versions of this method defined here
     * decompose the basic type into bytes and call this function.
     * If special processing is needed for a particular type your
     * subclass should override the method for that type.
     */
    public abstract void update(byte aValue);

    /**
     * Add a boolean to the digest.
     */
    public synchronized void update(boolean aValue) {
        byte    b;

        if (aValue)
            b = 1;
        else
            b = 0;
        update(b);
    }

    /**
     * Add a short value to the digest.
     */
    public synchronized void update(short aValue) {
        byte    b1, b2;

        b1 = (byte)((aValue >>> 8) & 0xff);
        b2 = (byte)(aValue & 0xff);
        update(b1);
        update(b2);
    }

    /**
     * Add an integer value to the digest.
     */
    public synchronized void update(int aValue) {
        byte    b;

        for (int i = 3; i >= 0; i--) {
            b = (byte)((aValue >>> (i * 8)) & 0xff);
            update(b);
        }
    }

    /**
     * Add a long to the digest.
     */
    public synchronized void update(long aValue) {
        byte    b;

        for (int i = 7; i >= 0; i--) {
            b = (byte)((aValue >>> (i * 8)) & 0xff);
            update(b);
        }
    }

    /**
     * Add specific bytes to the digest.
     */
    public synchronized void update(byte input[], int offset, int len) {
        for (int i = 0; i < len; i++) {
            update(input[i+offset]);
        }
    }

    /**
     * Add an array of bytes to the digest.
     */
    public synchronized void update(byte input[]) {
        update(input, 0, input.length);
    }

    /**
     * Add an array of shorts to the digest.
     */
    public synchronized void update(short input[]) {
        for (int i = 0; i < input.length; i++) {
            update(input[i]);
        }
    }

    /**
     * Add an array of integers to the digest.
     */
    public synchronized void update(int input[]) {
        for (int i = 0; i < input.length; i++) {
            update(input[i]);
        }
    }

    /**
     * Add an array of longs to the digest.
     */
    public synchronized void update(long input[]) {
        for (int i = 0; i < input.length; i++) {
            update(input[i]);
        }
    }

    /**
     * Add the bytes in the String 'input' to the current digest.
     * Note that the string characters are treated as unicode chars
     * of 16 bits each. To digestify ISO-Latin1 strings (ASCII) use
     * the updateASCII() method.
     */
    public void update(String input) {
        int     i, len;
        short   x;

        len = input.length();
        for (i = 0; i < len; i++) {
            x = (short) input.charAt(i);
            update(x);
        }
    }

    /**
     * Treat the string as a sequence of ISO-Latin1 (8 bit) characters.
     */
    public void updateASCII(String input) {
        int     i, len;
        byte    x;

        len = input.length();
        for (i = 0; i < len; i++) {
            x = (byte) (input.charAt(i) & 0xff);
            update(x);
        }
    }

    /**
     * Read a stream and update a digest until the
     * stream sends an EOF.
     */
    public void update(InputStream in) {
        byte    b;

        try {
            while ((b = (byte) in.read()) != -1)
                update(b);
        } catch (Exception e) { }
    }

    /**
     * Perform the final computations and cleanup.
     */
    public abstract void finish();

    /**
     * Complete digest computation on an array of bytes.
     */
    public void computeDigest(byte source[]) {
        init();
        update(source);
        finish();
    }

    public void computeDigest(InputStream in) {
        init();
        update(in);
        finish();
    }

    /**
     * helper function that prints unsigned two character hex digits.
     */
    private void hexDigit(PrintStream p, byte x) {
        char c;

        c = (char) ((x >> 4) & 0xf);
        if (c > 9)
                c = (char) ((c - 10) + 'A');
        else
                c = (char) (c + '0');
        p.write(c);
        c = (char) (x & 0xf);
        if (c > 9)
                c = (char)((c-10) + 'A');
        else
                c = (char)(c + '0');
        p.write(c);
    }

    /**
     * Return a string representation of this object.
     */
    public String toString() {
        ByteArrayOutputStream ou = new ByteArrayOutputStream();
        PrintStream p = new PrintStream(ou);

        p.print(this.getClass().getName()+" Message Digest ");
        if (digestValid) {
            p.print("<");
            for(int i = 0; i < digestBits.length; i++)
                hexDigit(p, digestBits[i]);
            p.print(">");
        } else {
            p.print("<incomplete>");
        }
        p.println();
        return (ou.toString());
    }

    /**
     * Compare two digests for equality. Simple byte compare.
     */
    public static boolean isEqual(byte digesta[], byte digestb[]) {
        int     i;

        if (digesta.length != digestb.length)
            return (false);

        for (i = 0; i < digesta.length; i++) {
            if (digesta[i] != digestb[i]) {
                return (false);
            }
        }
        return (true);
    }

    /**
     * Non static version that compares this digest to one passed.
     */
    public boolean isEqual(byte otherDigest[]) {
            return (MessageDigest.isEqual(digestBits, otherDigest));
    }

    /**
     * Return a string that represents the algorithim of this
     * message digest.
     */
    public abstract String getAlg();

    static byte testdata[];

    public static void benchmark(MessageDigest md) {
        Random rnd = new Random(); // use random data
        testdata = new byte[16384];
        long times[] = new long[14];
        double rates[] = new double[14];

        for (int i = 0; i < testdata.length; i++) {
            testdata[i] = (byte) (rnd.nextInt() >>> 8);
        }
        System.out.println("Benchmarking "+md.getAlg());
        System.out.println("Bytes   Time (mS)   Rate (Bytes/Sec)");
        for (int i = 1; i < 10; i++) {
            long t1 = System.currentTimeMillis();
            md.init();
            for (int k = 0; k < i; k++)
                md.update(testdata);
            md.finish();
            times[i] = System.currentTimeMillis() - t1;
            rates[i] = ((double) (i*testdata.length) * 1000.0)/ (double) times[i];
            System.out.println((i*testdata.length)+"\t"+times[i]+"\t"+rates[i]);
        }
        System.out.println("Done.");
    }

}

Have a nice day,
Ionel CONDOR.


Risto Reinpold wrote:

> Hi,
>
> How can I calculate md5 hash of String in Java.
>
> Thanks,
>
> Risto
>
> ===========================================================================
> To unsubscribe: mailto [EMAIL PROTECTED] with body: "signoff JSP-INTEREST".
> Some relevant FAQs on JSP/Servlets can be found at:
>
>  http://java.sun.com/products/jsp/faq.html
>  http://www.esperanto.org.nz/jsp/jspfaq.html
>  http://www.jguru.com/jguru/faq/faqpage.jsp?name=JSP
>  http://www.jguru.com/jguru/faq/faqpage.jsp?name=Servlets

===========================================================================
To unsubscribe: mailto [EMAIL PROTECTED] with body: "signoff JSP-INTEREST".
Some relevant FAQs on JSP/Servlets can be found at:

 http://java.sun.com/products/jsp/faq.html
 http://www.esperanto.org.nz/jsp/jspfaq.html
 http://www.jguru.com/jguru/faq/faqpage.jsp?name=JSP
 http://www.jguru.com/jguru/faq/faqpage.jsp?name=Servlets

Reply via email to