1 /* Copyright (c) 2000 The Legion Of The Bouncy Castle
2 * (http://www.bouncycastle.org)
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDER.S BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
23 package org.ibex.crypto;
26 * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
31 private static final int DIGEST_LENGTH = 16;
33 private int H1, H2, H3, H4; // IV's
35 private int[] X = new int[16];
39 * Standard constructor
46 public int getDigestSize()
51 protected void processWord(
55 X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
56 | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
64 protected void processLength(
72 X[14] = (int)(bitLength & 0xffffffff);
73 X[15] = (int)(bitLength >>> 32);
76 private void unpackWord(
81 out[outOff] = (byte)word;
82 out[outOff + 1] = (byte)(word >>> 8);
83 out[outOff + 2] = (byte)(word >>> 16);
84 out[outOff + 3] = (byte)(word >>> 24);
93 unpackWord(H1, out, outOff);
94 unpackWord(H2, out, outOff + 4);
95 unpackWord(H3, out, outOff + 8);
96 unpackWord(H4, out, outOff + 12);
102 * reset the chaining variables to the IV values.
115 for (int i = 0; i != X.length; i++)
122 * rotate int x left n bits.
124 private int rotateLeft(
128 return (x << n) | (x >>> (32 - n));
132 * F, G, H and I are the basic MD5 functions.
139 return (u & v) | (~u & w);
147 return (u & w) | (v & ~w);
166 protected void processBlock()
174 // Round 1 - F cycle, 16 times.
176 a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), 7) + b;
177 d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), 12) + a;
178 c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), 17) + d;
179 b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), 22) + c;
180 a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), 7) + b;
181 d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), 12) + a;
182 c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), 17) + d;
183 b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), 22) + c;
184 a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), 7) + b;
185 d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), 12) + a;
186 c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), 17) + d;
187 b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), 22) + c;
188 a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), 7) + b;
189 d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), 12) + a;
190 c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), 17) + d;
191 b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), 22) + c;
194 // Round 2 - G cycle, 16 times.
196 a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), 5) + b;
197 d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), 9) + a;
198 c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), 14) + d;
199 b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), 20) + c;
200 a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), 5) + b;
201 d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), 9) + a;
202 c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), 14) + d;
203 b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), 20) + c;
204 a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), 5) + b;
205 d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), 9) + a;
206 c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), 14) + d;
207 b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), 20) + c;
208 a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), 5) + b;
209 d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), 9) + a;
210 c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), 14) + d;
211 b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), 20) + c;
214 // Round 3 - H cycle, 16 times.
216 a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), 4) + b;
217 d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), 11) + a;
218 c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), 16) + d;
219 b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), 23) + c;
220 a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), 4) + b;
221 d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), 11) + a;
222 c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), 16) + d;
223 b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), 23) + c;
224 a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), 4) + b;
225 d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), 11) + a;
226 c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), 16) + d;
227 b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), 23) + c;
228 a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), 4) + b;
229 d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), 11) + a;
230 c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), 16) + d;
231 b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), 23) + c;
234 // Round 4 - K cycle, 16 times.
236 a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), 6) + b;
237 d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), 10) + a;
238 c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), 15) + d;
239 b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), 21) + c;
240 a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), 6) + b;
241 d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), 10) + a;
242 c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), 15) + d;
243 b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), 21) + c;
244 a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), 6) + b;
245 d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), 10) + a;
246 c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), 15) + d;
247 b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), 21) + c;
248 a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), 6) + b;
249 d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), 10) + a;
250 c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), 15) + d;
251 b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), 21) + c;
259 // reset the offset and clean out the word buffer.
262 for (int i = 0; i != X.length; i++)