Java tutorial
/* * Copyright 2010 Google Inc. * * 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. */ /* * MODIFIED BY GOOGLE * * Originally taken from org.apache.java.security.MD5 fetched from: * <pre> * http://archive.apache.org/dist/turbine/turbine-2.1/source/turbine-src-2.1b3.tar.gz * </pre> * * Modified by removing test data, changing style to match GWT style guide, * and making it better conform to MessageDigestSpi. * * Original license below: */ /* * ==================================================================== The * Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if and * wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and "Apache Turbine" * must not be used to endorse or promote products derived from this software * without prior written permission. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Apache Turbine", nor may "Apache" appear in their name, without prior * written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE * SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many individuals on * behalf of the Apache Software Foundation. For more information on the Apache * Software Foundation, please see <http://www.apache.org/>. */ /* * This class implements the Message Digest 5 algorithm (MD5) as defined in * <a href="http://tools.ietf.org/html/rfc1321">RFC-1321</a>. * * <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> */ package com.google.gwt.core.client.impl; import java.security.MessageDigest; /** * GWT implementation of MD5. */ public final class Md5Digest extends MessageDigest { // 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 }; /** * 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; } /** * 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] = ((in[inpos++] & 0xff) | ((in[inpos++] & 0xff) << 8) | ((in[inpos++] & 0xff) << 16) | ((in[inpos++] & 0xff) << 24)); } } /* * Method F. * * @param x An int. * @param y An int. * @param z An int. * @return An int. */ private static 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. */ private static 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. */ private static 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. */ private static 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. */ private static 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. */ private static 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. */ private static 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. */ private static 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); } } private byte buffer[]; // TODO(jat): consider doing away with long math private long counter; private final byte[] oneByte = new byte[1]; private int remainder; private int state[]; private int x[]; public Md5Digest() { super("MD5"); engineReset(); } @Override protected byte[] engineDigest() { byte[] bits = toBytes(counter << 3); byte[] digest = new byte[16]; if (remainder > 8) { engineUpdate(padding, 0, remainder - 8); } else { engineUpdate(padding, 0, 64 + (remainder - 8)); } engineUpdate(bits, 0, 8); int2byte(state, digest); this.reset(); return digest; } @Override protected int engineGetDigestLength() { return 16; } @Override protected void engineReset() { 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; remainder = 64; } @Override protected void engineUpdate(byte input) { // TODO(jat): better implementation oneByte[0] = input; engineUpdate(oneByte, 0, 1); } @Override protected void engineUpdate(byte[] input, int offset, int len) { while (true) { if (len >= remainder) { System.arraycopy(input, offset, buffer, (int) (counter & 63L), remainder); transform(buffer); counter += remainder; offset += remainder; len -= remainder; remainder = 64; } else { System.arraycopy(input, offset, buffer, (int) (counter & 63L), len); counter += len; remainder -= len; break; } } } /* * 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; } }