MD5.java :  » Project-Management » turbine » org » apache » java » security » Java Open Source

Java Open Source » Project Management » turbine 
turbine » org » apache » java » security » MD5.java
package org.apache.java.security;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * 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.
 */

/**
 * This class implements the Message Digest 5 algorithm (MD5) as
 * defined in RFC-1321.
 *
 * <p><b>Note:</b> even if standard Java 1.1 APIs already provide a
 * MD5 implementation, this class is used on those Java runtime
 * environments (like Kaffe) where the package
 * <code>java.security</code> is highly improbable to be found.
 *
 * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
 * @version $Id: MD5.java 264148 2005-08-29 14:21:04Z henning $
 * @deprecated Use the java.security package.
 */
public final class MD5
    extends MessageDigest
{
    private long counter;
    private int reminder;
    private byte buffer[];
    private int state[];
    private int x[];

    /*********************** MD5 Functions ***********************/

    // 16 * 4 bytes
    static byte padding[] =
    {
        (byte) 0x80,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };

    /*********************** Self Test ***********************/

    private static String[] messages =
    {
        "",
        "a",
        "abc",
        "message digest",
        "abcdefghijklmnopqrstuvwxyz",
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
        "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
    };

    private static String[] digests =
    {
        "d41d8cd98f00b204e9800998ecf8427e",
        "0cc175b9c0f1b6a831c399e269772661",
        "900150983cd24fb0d6963f7d28e17f72",
        "f96b697d7cb7938d525a2f31aaf161d0",
        "c3fcd3d76192e4007dfb496cca67e13b",
        "d174ab98d277d9f5a5611c2c9f419d9f",
        "57edf4a22be3c955ac49da2e2107b67a",
    };


    /**
     * Creates the algorithm and reset its state.
     */
    public MD5()
    {
        super();
    }

    /**
     * Append another block of specified length to the message
     * starting at the given offset.
     *
     * @param block A byte[].
     * @param offset An int.
     * @param length An int.
     */
    public void append(byte[] block,
                       int offset,
                       int length)
    {
        while (true)
        {
            if (length >= reminder)
            {
                System.arraycopy(block, offset, buffer,
                                 (int) (counter & 63L), reminder);
                transform(buffer);
                counter += reminder;
                offset += reminder;
                length -= reminder;
                reminder = 64;
            }
            else
            {
                System.arraycopy(block, offset, buffer,
                                 (int) (counter & 63L), length);
                counter += length;
                reminder -= length;
                break;
            }
        }
    }

    /*********************** Byte/Int utilities ***********************/

    /**
     * Converts a 64-byte array into a 16-int array.
     *
     * @param in A byte[].
     * @param out An int[].
     */
    private static void byte2int(byte[] in,
                                 int[] out)
    {
        for (int inpos = 0, outpos = 0; outpos < 16; outpos++)
        {
            out[outpos] = ((((int) (in[inpos++] & 0xff))) |
                           (((int) (in[inpos++] & 0xff)) << 8) |
                           (((int) (in[inpos++] & 0xff)) << 16) |
                           (((int) (in[inpos++] & 0xff)) << 24));
        }
    }

    /**
     * Appends a message block with specified length starting from the
     * given offset, and return its message digest.
     *
     * @param block A byte[].
     * @param offset An int.
     * @param length An int.
     */
    public byte[] digest(byte[] block,
                         int offset,
                         int length)
    {
        this.append(block, offset, length);

        byte[] bits = toBytes(counter << 3);
        byte[] digest = new byte[16];

        if (reminder > 8)
        {
            append(padding, 0, reminder - 8);
        }
        else
        {
            append(padding, 0, 64 + (reminder - 8));
        }

        append(bits, 0, 8);

        int2byte(state, digest);

        this.reset();
        return digest;
    }

    /*
     * Method F.
     *
     * @param x An int.
     * @param y An int.
     * @param z An int.
     * @return An int.
     */
    static private int F(int x,
                         int y,
                         int z)
    {
        return (z ^ (x & (y^z)));
    }

    /*
     * Method FF.
     *
     * @param a An int.
     * @param b An int.
     * @param c An int.
     * @param d An int.
     * @param x An int.
     * @param s An int.
     * @param ac An int.
     * @return An int.
     */
    static private int FF(int a,
                          int b,
                          int c,
                          int d,
                          int x,
                          int s,
                          int ac)
    {
        a += x + ac + F(b,c,d);
        a = (a << s | a >>> -s);
        return a + b;
    }

    /*
     * Method G.
     *
     * @param x An int.
     * @param y An int.
     * @param z An int.
     * @return An int.
     */
    static private int G(int x,
                         int y,
                         int z)
    {
        return (y ^ (z & (x^y)));
    }

    /*
     * Method GG.
     *
     * @param a An int.
     * @param b An int.
     * @param c An int.
     * @param d An int.
     * @param x An int.
     * @param s An int.
     * @param ac An int.
     * @return An int.
     */
    static private int GG(int a,
                          int b,
                          int c,
                          int d,
                          int x,
                          int s,
                          int ac)
    {
        a += x + ac + G(b,c,d);
        a = (a << s | a >>> -s);
        return a + b;
    }

    /*
     * Method H.
     *
     * @param x An int.
     * @param y An int.
     * @param z An int.
     * @return An int.
     */
    static private int H(int x,
                         int y,
                         int z)
    {
        return (x ^ y ^ z);
    }

    /*
     * Method HH.
     *
     * @param a An int.
     * @param b An int.
     * @param c An int.
     * @param d An int.
     * @param x An int.
     * @param s An int.
     * @param ac An int.
     * @return An int.
     */
    static private int HH(int a,
                          int b,
                          int c,
                          int d,
                          int x,
                          int s,
                          int ac)
    {
        a += x + ac + H(b,c,d);
        a = (a << s | a >>> -s);
        return a + b;
    }

    /*
     * Method I.
     *
     * @param x An int.
     * @param y An int.
     * @param z An int.
     * @return An int.
     */
    static private int I(int x,
                         int y,
                         int z)
    {
        return (y ^ (x | ~z));
    }

    /*
     * Method II.
     *
     * @param a An int.
     * @param b An int.
     * @param c An int.
     * @param d An int.
     * @param x An int.
     * @param s An int.
     * @param ac An int.
     * @return An int.
     */
    static private int II(int a,
                          int b,
                          int c,
                          int d,
                          int x,
                          int s,
                          int ac)
    {
        a += x + ac + I(b,c,d);
        a = (a << s | a >>> -s);
        return a + b;
    }

    /**
     * Converts a 4-int array into a 16-byte array.
     *
     * @param in An int[].
     * @param out A byte[].
     */
    private static void int2byte(int[] in,
                                 byte[] out)
    {
        for (int inpos = 0, outpos = 0; inpos < 4; inpos++)
        {
            out[outpos++] = (byte) (in[inpos] & 0xff);
            out[outpos++] = (byte) ((in[inpos] >>> 8) & 0xff);
            out[outpos++] = (byte) ((in[inpos] >>> 16) & 0xff);
            out[outpos++] = (byte) ((in[inpos] >>> 24) & 0xff);
        }
    }

    /*
     * Main routine, for testing purposes only.
     *
     * @param ignored A String[] with the command line arguments.
     */
    public static final void main(String[] ignored)
    {
        MD5 md5 = new MD5();

        for (int i = 0; i < messages.length; i++)
        {
            String digest = org.apache.java.lang.Bytes.toString(
                md5.digest(messages[i].getBytes()));
            System.out.println("Computed: " + digest);
            System.out.println("Correct: " + digests[i]);
            if (digest.equalsIgnoreCase(digests[i]))
            {
                System.out.println("Test " + i + " passed.");
            }
            else
            {
                System.out.println("Test " + i + " failed.");
            }
        }
    }

    /**
     * Resets the state of the class.  <b>Beware</b>: calling this
     * method erases all data previously inserted.
     */
    public void reset()
    {
        buffer = new byte[64];
        state = new int[4];
        x = new int[16];

        state[0] = 0x67452301;
        state[1] = 0xefcdab89;
        state[2] = 0x98badcfe;
        state[3] = 0x10325476;

        counter = 0;
        reminder = 64;
    }

    /**
     * Converts a long to a 8-byte array using low order first.
     *
     * @param n A long.
     * @return A byte[].
     */
    public static byte[] toBytes(long n)
    {
        byte[] b = new byte[8];

        b[0] = (byte) (n);
        n >>>= 8;
        b[1] = (byte) (n);
        n >>>= 8;
        b[2] = (byte) (n);
        n >>>= 8;
        b[3] = (byte) (n);
        n >>>= 8;
        b[4] = (byte) (n);
        n >>>= 8;
        b[5] = (byte) (n);
        n >>>= 8;
        b[6] = (byte) (n);
        n >>>= 8;
        b[7] = (byte) (n);

        return b;
    }

    /*
     * TODO: Document.
     *
     * @param buffer A byte[].
     */
    private void transform(byte[] buffer)
    {
        int a, b, c, d;

        byte2int(buffer, x);

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

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

        a = GG(a, b, c, d, x[ 1],  5, 0xf61e2562);
        d = GG(d, a, b, c, x[ 6],  9, 0xc040b340);
        c = GG(c, d, a, b, x[11], 14, 0x265e5a51);
        b = GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
        a = GG(a, b, c, d, x[ 5],  5, 0xd62f105d);
        d = GG(d, a, b, c, x[10],  9,  0x2441453);
        c = GG(c, d, a, b, x[15], 14, 0xd8a1e681);
        b = GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
        a = GG(a, b, c, d, x[ 9],  5, 0x21e1cde6);
        d = GG(d, a, b, c, x[14],  9, 0xc33707d6);
        c = GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);
        b = GG(b, c, d, a, x[ 8], 20, 0x455a14ed);
        a = GG(a, b, c, d, x[13],  5, 0xa9e3e905);
        d = GG(d, a, b, c, x[ 2],  9, 0xfcefa3f8);
        c = GG(c, d, a, b, x[ 7], 14, 0x676f02d9);
        b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);

        a = HH(a, b, c, d, x[ 5],  4, 0xfffa3942);
        d = HH(d, a, b, c, x[ 8], 11, 0x8771f681);
        c = HH(c, d, a, b, x[11], 16, 0x6d9d6122);
        b = HH(b, c, d, a, x[14], 23, 0xfde5380c);
        a = HH(a, b, c, d, x[ 1],  4, 0xa4beea44);
        d = HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
        c = HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
        b = HH(b, c, d, a, x[10], 23, 0xbebfbc70);
        a = HH(a, b, c, d, x[13],  4, 0x289b7ec6);
        d = HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);
        c = HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);
        b = HH(b, c, d, a, x[ 6], 23,  0x4881d05);
        a = HH(a, b, c, d, x[ 9],  4, 0xd9d4d039);
        d = HH(d, a, b, c, x[12], 11, 0xe6db99e5);
        c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
        b = HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);

        a = II(a, b, c, d, x[ 0],  6, 0xf4292244);
        d = II(d, a, b, c, x[ 7], 10, 0x432aff97);
        c = II(c, d, a, b, x[14], 15, 0xab9423a7);
        b = II(b, c, d, a, x[ 5], 21, 0xfc93a039);
        a = II(a, b, c, d, x[12],  6, 0x655b59c3);
        d = II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
        c = II(c, d, a, b, x[10], 15, 0xffeff47d);
        b = II(b, c, d, a, x[ 1], 21, 0x85845dd1);
        a = II(a, b, c, d, x[ 8],  6, 0x6fa87e4f);
        d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
        c = II(c, d, a, b, x[ 6], 15, 0xa3014314);
        b = II(b, c, d, a, x[13], 21, 0x4e0811a1);
        a = II(a, b, c, d, x[ 4],  6, 0xf7537e82);
        d = II(d, a, b, c, x[11], 10, 0xbd3af235);
        c = II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
        b = II(b, c, d, a, x[ 9], 21, 0xeb86d391);

        state[0] += a;
        state[1] += b;
        state[2] += c;
        state[3] += d;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.