|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.provider; |
|
|
|
import java.lang.invoke.MethodHandles; |
|
import java.lang.invoke.VarHandle; |
|
import java.nio.ByteOrder; |
|
import java.util.Arrays; |
|
import java.util.Objects; |
|
|
|
import static sun.security.provider.ByteArrayAccess.*; |
|
import jdk.internal.vm.annotation.IntrinsicCandidate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class MD5 extends DigestBase { |
|
|
|
|
|
private int[] state; |
|
|
|
|
|
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; |
|
|
|
|
|
public MD5() { |
|
super("MD5", 16, 64); |
|
state = new int[4]; |
|
implReset(); |
|
} |
|
|
|
|
|
public Object clone() throws CloneNotSupportedException { |
|
MD5 copy = (MD5) super.clone(); |
|
copy.state = copy.state.clone(); |
|
return copy; |
|
} |
|
|
|
|
|
|
|
*/ |
|
void implReset() { |
|
|
|
state[0] = 0x67452301; |
|
state[1] = 0xefcdab89; |
|
state[2] = 0x98badcfe; |
|
state[3] = 0x10325476; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void implDigest(byte[] out, int ofs) { |
|
long bitsProcessed = bytesProcessed << 3; |
|
|
|
int index = (int)bytesProcessed & 0x3f; |
|
int padLen = (index < 56) ? (56 - index) : (120 - index); |
|
engineUpdate(padding, 0, padLen); |
|
|
|
i2bLittle4((int)bitsProcessed, buffer, 56); |
|
i2bLittle4((int)(bitsProcessed >>> 32), buffer, 60); |
|
implCompress(buffer, 0); |
|
|
|
i2bLittle(state, 0, out, ofs, 16); |
|
} |
|
|
|
/* ********************************************************** |
|
* The MD5 Functions. The results of this |
|
* implementation were checked against the RSADSI version. |
|
* ********************************************************** |
|
*/ |
|
|
|
private static int FF(int a, int b, int c, int d, int x, int s, int ac) { |
|
a += ((b & c) | ((~b) & d)) + x + ac; |
|
return ((a << s) | (a >>> (32 - s))) + b; |
|
} |
|
|
|
private static int GG(int a, int b, int c, int d, int x, int s, int ac) { |
|
a += ((b & d) | (c & (~d))) + x + ac; |
|
return ((a << s) | (a >>> (32 - s))) + b; |
|
} |
|
|
|
private static int HH(int a, int b, int c, int d, int x, int s, int ac) { |
|
a += ((b ^ c) ^ d) + x + ac; |
|
return ((a << s) | (a >>> (32 - s))) + b; |
|
} |
|
|
|
private static int II(int a, int b, int c, int d, int x, int s, int ac) { |
|
a += (c ^ (b | (~d))) + x + ac; |
|
return ((a << s) | (a >>> (32 - s))) + b; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void implCompress(byte[] buf, int ofs) { |
|
implCompressCheck(buf, ofs); |
|
implCompress0(buf, ofs); |
|
} |
|
|
|
private void implCompressCheck(byte[] buf, int ofs) { |
|
Objects.requireNonNull(buf); |
|
|
|
// These checks are sufficient for the case when the method |
|
// 'implCompressImpl' is replaced with a compiler |
|
|
|
if ((ofs < 0) || ((buf.length - ofs) < 64)) { |
|
throw new ArrayIndexOutOfBoundsException(); |
|
} |
|
} |
|
|
|
// The method 'implCompress0 seems not to use its parameters. |
|
// The method can, however, be replaced with a compiler intrinsic |
|
// that operates directly on the array 'buf' (starting from |
|
// offset 'ofs') and not on array 'x', therefore 'buf' and 'ofs' |
|
|
|
@IntrinsicCandidate |
|
void implCompress0(byte[] buf, int ofs) { |
|
int a = state[0]; |
|
int b = state[1]; |
|
int c = state[2]; |
|
int d = state[3]; |
|
|
|
int x0 = (int) LE.INT_ARRAY.get(buf, ofs); |
|
int x1 = (int) LE.INT_ARRAY.get(buf, ofs + 4); |
|
int x2 = (int) LE.INT_ARRAY.get(buf, ofs + 8); |
|
int x3 = (int) LE.INT_ARRAY.get(buf, ofs + 12); |
|
int x4 = (int) LE.INT_ARRAY.get(buf, ofs + 16); |
|
int x5 = (int) LE.INT_ARRAY.get(buf, ofs + 20); |
|
int x6 = (int) LE.INT_ARRAY.get(buf, ofs + 24); |
|
int x7 = (int) LE.INT_ARRAY.get(buf, ofs + 28); |
|
int x8 = (int) LE.INT_ARRAY.get(buf, ofs + 32); |
|
int x9 = (int) LE.INT_ARRAY.get(buf, ofs + 36); |
|
int x10 = (int) LE.INT_ARRAY.get(buf, ofs + 40); |
|
int x11 = (int) LE.INT_ARRAY.get(buf, ofs + 44); |
|
int x12 = (int) LE.INT_ARRAY.get(buf, ofs + 48); |
|
int x13 = (int) LE.INT_ARRAY.get(buf, ofs + 52); |
|
int x14 = (int) LE.INT_ARRAY.get(buf, ofs + 56); |
|
int x15 = (int) LE.INT_ARRAY.get(buf, ofs + 60); |
|
|
|
|
|
a = FF ( a, b, c, d, x0, S11, 0xd76aa478); |
|
d = FF ( d, a, b, c, x1, S12, 0xe8c7b756); |
|
c = FF ( c, d, a, b, x2, S13, 0x242070db); |
|
b = FF ( b, c, d, a, x3, S14, 0xc1bdceee); |
|
a = FF ( a, b, c, d, x4, S11, 0xf57c0faf); |
|
d = FF ( d, a, b, c, x5, S12, 0x4787c62a); |
|
c = FF ( c, d, a, b, x6, S13, 0xa8304613); |
|
b = FF ( b, c, d, a, x7, S14, 0xfd469501); |
|
a = FF ( a, b, c, d, x8, S11, 0x698098d8); |
|
d = FF ( d, a, b, c, x9, S12, 0x8b44f7af); |
|
c = FF ( c, d, a, b, x10, S13, 0xffff5bb1); |
|
b = FF ( b, c, d, a, x11, S14, 0x895cd7be); |
|
a = FF ( a, b, c, d, x12, S11, 0x6b901122); |
|
d = FF ( d, a, b, c, x13, S12, 0xfd987193); |
|
c = FF ( c, d, a, b, x14, S13, 0xa679438e); |
|
b = FF ( b, c, d, a, x15, S14, 0x49b40821); /* 16 */ |
|
|
|
|
|
a = GG ( a, b, c, d, x1, S21, 0xf61e2562); |
|
d = GG ( d, a, b, c, x6, S22, 0xc040b340); |
|
c = GG ( c, d, a, b, x11, S23, 0x265e5a51); |
|
b = GG ( b, c, d, a, x0, S24, 0xe9b6c7aa); |
|
a = GG ( a, b, c, d, x5, S21, 0xd62f105d); |
|
d = GG ( d, a, b, c, x10, S22, 0x2441453); |
|
c = GG ( c, d, a, b, x15, S23, 0xd8a1e681); |
|
b = GG ( b, c, d, a, x4, S24, 0xe7d3fbc8); |
|
a = GG ( a, b, c, d, x9, S21, 0x21e1cde6); |
|
d = GG ( d, a, b, c, x14, S22, 0xc33707d6); |
|
c = GG ( c, d, a, b, x3, S23, 0xf4d50d87); |
|
b = GG ( b, c, d, a, x8, S24, 0x455a14ed); |
|
a = GG ( a, b, c, d, x13, S21, 0xa9e3e905); |
|
d = GG ( d, a, b, c, x2, S22, 0xfcefa3f8); |
|
c = GG ( c, d, a, b, x7, S23, 0x676f02d9); |
|
b = GG ( b, c, d, a, x12, S24, 0x8d2a4c8a); /* 32 */ |
|
|
|
|
|
a = HH ( a, b, c, d, x5, S31, 0xfffa3942); |
|
d = HH ( d, a, b, c, x8, S32, 0x8771f681); |
|
c = HH ( c, d, a, b, x11, S33, 0x6d9d6122); |
|
b = HH ( b, c, d, a, x14, S34, 0xfde5380c); |
|
a = HH ( a, b, c, d, x1, S31, 0xa4beea44); |
|
d = HH ( d, a, b, c, x4, S32, 0x4bdecfa9); |
|
c = HH ( c, d, a, b, x7, S33, 0xf6bb4b60); |
|
b = HH ( b, c, d, a, x10, S34, 0xbebfbc70); |
|
a = HH ( a, b, c, d, x13, S31, 0x289b7ec6); |
|
d = HH ( d, a, b, c, x0, S32, 0xeaa127fa); |
|
c = HH ( c, d, a, b, x3, S33, 0xd4ef3085); |
|
b = HH ( b, c, d, a, x6, S34, 0x4881d05); |
|
a = HH ( a, b, c, d, x9, S31, 0xd9d4d039); |
|
d = HH ( d, a, b, c, x12, S32, 0xe6db99e5); |
|
c = HH ( c, d, a, b, x15, S33, 0x1fa27cf8); |
|
b = HH ( b, c, d, a, x2, S34, 0xc4ac5665); /* 48 */ |
|
|
|
|
|
a = II ( a, b, c, d, x0, S41, 0xf4292244); |
|
d = II ( d, a, b, c, x7, S42, 0x432aff97); |
|
c = II ( c, d, a, b, x14, S43, 0xab9423a7); |
|
b = II ( b, c, d, a, x5, S44, 0xfc93a039); |
|
a = II ( a, b, c, d, x12, S41, 0x655b59c3); |
|
d = II ( d, a, b, c, x3, S42, 0x8f0ccc92); |
|
c = II ( c, d, a, b, x10, S43, 0xffeff47d); |
|
b = II ( b, c, d, a, x1, S44, 0x85845dd1); |
|
a = II ( a, b, c, d, x8, S41, 0x6fa87e4f); |
|
d = II ( d, a, b, c, x15, S42, 0xfe2ce6e0); |
|
c = II ( c, d, a, b, x6, S43, 0xa3014314); |
|
b = II ( b, c, d, a, x13, S44, 0x4e0811a1); |
|
a = II ( a, b, c, d, x4, S41, 0xf7537e82); |
|
d = II ( d, a, b, c, x11, S42, 0xbd3af235); |
|
c = II ( c, d, a, b, x2, S43, 0x2ad7d2bb); |
|
b = II ( b, c, d, a, x9, S44, 0xeb86d391); /* 64 */ |
|
|
|
state[0] += a; |
|
state[1] += b; |
|
state[2] += c; |
|
state[3] += d; |
|
} |
|
|
|
} |