diff --git a/user/src/com/google/gwt/core/client/impl/Md5Digest.java b/user/src/com/google/gwt/core/client/impl/Md5Digest.java deleted file mode 100644 index 53ebe582d2e..00000000000 --- a/user/src/com/google/gwt/core/client/impl/Md5Digest.java +++ /dev/null @@ -1,455 +0,0 @@ -/* - * 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: - *
- * http://archive.apache.org/dist/turbine/turbine-2.1/source/turbine-src-2.1b3.tar.gz
- * 
- * - * 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 . - */ -/* - * This class implements the Message Digest 5 algorithm (MD5) as defined in - * RFC-1321. - * - *

Note: 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 java.security is highly improbable to - * be found. - * - * author Stefano Mazzocchi - */ -package com.google.gwt.core.client.impl; - -import static com.google.gwt.core.client.impl.Coercions.ensureInt; - -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); - - // Coerce to 32-bits to compute the expression correctly in JavaScript. - state[0] = ensureInt(state[0] + a); - state[1] = ensureInt(state[1] + b); - state[2] = ensureInt(state[2] + c); - state[3] = ensureInt(state[3] + d); - } -} diff --git a/user/super/com/google/gwt/emul/java/security/MessageDigest.java b/user/super/com/google/gwt/emul/java/security/MessageDigest.java index 851cd7bf6d1..3f89c7ea833 100644 --- a/user/super/com/google/gwt/emul/java/security/MessageDigest.java +++ b/user/super/com/google/gwt/emul/java/security/MessageDigest.java @@ -1,12 +1,12 @@ /* * 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 @@ -15,7 +15,7 @@ */ package java.security; -import com.google.gwt.core.client.impl.Md5Digest; +import static com.google.gwt.core.client.impl.Coercions.ensureInt; /** * Message Digest algorithm - >>= 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); + + // Coerce to 32-bits to compute the expression correctly in JavaScript. + state[0] = ensureInt(state[0] + a); + state[1] = ensureInt(state[1] + b); + state[2] = ensureInt(state[2] + c); + state[3] = ensureInt(state[3] + d); + } + } + public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException { if ("MD5".equals(algorithm)) {