001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.util.crypto.digests; 019 020 021 /** 022 * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347. 023 */ 024 public class MD5Digest 025 extends GeneralDigest 026 { 027 private static final int DIGEST_LENGTH = 16; 028 029 private int H1, H2, H3, H4; // IV's 030 031 private int[] X = new int[16]; 032 private int xOff; 033 034 /** 035 * Standard constructor 036 */ 037 public MD5Digest() 038 { 039 reset(); 040 } 041 042 /** 043 * Copy constructor. This will copy the state of the provided 044 * message digest. 045 */ 046 public MD5Digest(MD5Digest t) 047 { 048 super(t); 049 050 H1 = t.H1; 051 H2 = t.H2; 052 H3 = t.H3; 053 H4 = t.H4; 054 055 System.arraycopy(t.X, 0, X, 0, t.X.length); 056 xOff = t.xOff; 057 } 058 059 public String getAlgorithmName() 060 { 061 return "MD5"; 062 } 063 064 public int getDigestSize() 065 { 066 return DIGEST_LENGTH; 067 } 068 069 protected void processWord( 070 byte[] in, 071 int inOff) 072 { 073 X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) 074 | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 075 076 if (xOff == 16) 077 { 078 processBlock(); 079 } 080 } 081 082 protected void processLength( 083 long bitLength) 084 { 085 if (xOff > 14) 086 { 087 processBlock(); 088 } 089 090 X[14] = (int)(bitLength & 0xffffffff); 091 X[15] = (int)(bitLength >>> 32); 092 } 093 094 private void unpackWord( 095 int word, 096 byte[] out, 097 int outOff) 098 { 099 out[outOff] = (byte)word; 100 out[outOff + 1] = (byte)(word >>> 8); 101 out[outOff + 2] = (byte)(word >>> 16); 102 out[outOff + 3] = (byte)(word >>> 24); 103 } 104 105 public int doFinal( 106 byte[] out, 107 int outOff) 108 { 109 finish(); 110 111 unpackWord(H1, out, outOff); 112 unpackWord(H2, out, outOff + 4); 113 unpackWord(H3, out, outOff + 8); 114 unpackWord(H4, out, outOff + 12); 115 116 reset(); 117 118 return DIGEST_LENGTH; 119 } 120 121 /** 122 * reset the chaining variables to the IV values. 123 */ 124 public void reset() 125 { 126 super.reset(); 127 128 H1 = 0x67452301; 129 H2 = 0xefcdab89; 130 H3 = 0x98badcfe; 131 H4 = 0x10325476; 132 133 xOff = 0; 134 135 for (int i = 0; i != X.length; i++) 136 { 137 X[i] = 0; 138 } 139 } 140 141 // 142 // round 1 left rotates 143 // 144 private static final int S11 = 7; 145 private static final int S12 = 12; 146 private static final int S13 = 17; 147 private static final int S14 = 22; 148 149 // 150 // round 2 left rotates 151 // 152 private static final int S21 = 5; 153 private static final int S22 = 9; 154 private static final int S23 = 14; 155 private static final int S24 = 20; 156 157 // 158 // round 3 left rotates 159 // 160 private static final int S31 = 4; 161 private static final int S32 = 11; 162 private static final int S33 = 16; 163 private static final int S34 = 23; 164 165 // 166 // round 4 left rotates 167 // 168 private static final int S41 = 6; 169 private static final int S42 = 10; 170 private static final int S43 = 15; 171 private static final int S44 = 21; 172 173 /* 174 * rotate int x left n bits. 175 */ 176 private int rotateLeft( 177 int x, 178 int n) 179 { 180 return (x << n) | (x >>> (32 - n)); 181 } 182 183 /* 184 * F, G, H and I are the basic MD5 functions. 185 */ 186 private int F( 187 int u, 188 int v, 189 int w) 190 { 191 return (u & v) | (~u & w); 192 } 193 194 private int G( 195 int u, 196 int v, 197 int w) 198 { 199 return (u & w) | (v & ~w); 200 } 201 202 private int H( 203 int u, 204 int v, 205 int w) 206 { 207 return u ^ v ^ w; 208 } 209 210 private int K( 211 int u, 212 int v, 213 int w) 214 { 215 return v ^ (u | ~w); 216 } 217 218 protected void processBlock() 219 { 220 int a = H1; 221 int b = H2; 222 int c = H3; 223 int d = H4; 224 225 // 226 // Round 1 - F cycle, 16 times. 227 // 228 a = rotateLeft(a + F(b, c, d) + X[ 0] + 0xd76aa478, S11) + b; 229 d = rotateLeft(d + F(a, b, c) + X[ 1] + 0xe8c7b756, S12) + a; 230 c = rotateLeft(c + F(d, a, b) + X[ 2] + 0x242070db, S13) + d; 231 b = rotateLeft(b + F(c, d, a) + X[ 3] + 0xc1bdceee, S14) + c; 232 a = rotateLeft(a + F(b, c, d) + X[ 4] + 0xf57c0faf, S11) + b; 233 d = rotateLeft(d + F(a, b, c) + X[ 5] + 0x4787c62a, S12) + a; 234 c = rotateLeft(c + F(d, a, b) + X[ 6] + 0xa8304613, S13) + d; 235 b = rotateLeft(b + F(c, d, a) + X[ 7] + 0xfd469501, S14) + c; 236 a = rotateLeft(a + F(b, c, d) + X[ 8] + 0x698098d8, S11) + b; 237 d = rotateLeft(d + F(a, b, c) + X[ 9] + 0x8b44f7af, S12) + a; 238 c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d; 239 b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c; 240 a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b; 241 d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a; 242 c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d; 243 b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c; 244 245 // 246 // Round 2 - G cycle, 16 times. 247 // 248 a = rotateLeft(a + G(b, c, d) + X[ 1] + 0xf61e2562, S21) + b; 249 d = rotateLeft(d + G(a, b, c) + X[ 6] + 0xc040b340, S22) + a; 250 c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d; 251 b = rotateLeft(b + G(c, d, a) + X[ 0] + 0xe9b6c7aa, S24) + c; 252 a = rotateLeft(a + G(b, c, d) + X[ 5] + 0xd62f105d, S21) + b; 253 d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a; 254 c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d; 255 b = rotateLeft(b + G(c, d, a) + X[ 4] + 0xe7d3fbc8, S24) + c; 256 a = rotateLeft(a + G(b, c, d) + X[ 9] + 0x21e1cde6, S21) + b; 257 d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a; 258 c = rotateLeft(c + G(d, a, b) + X[ 3] + 0xf4d50d87, S23) + d; 259 b = rotateLeft(b + G(c, d, a) + X[ 8] + 0x455a14ed, S24) + c; 260 a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b; 261 d = rotateLeft(d + G(a, b, c) + X[ 2] + 0xfcefa3f8, S22) + a; 262 c = rotateLeft(c + G(d, a, b) + X[ 7] + 0x676f02d9, S23) + d; 263 b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c; 264 265 // 266 // Round 3 - H cycle, 16 times. 267 // 268 a = rotateLeft(a + H(b, c, d) + X[ 5] + 0xfffa3942, S31) + b; 269 d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x8771f681, S32) + a; 270 c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d; 271 b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c; 272 a = rotateLeft(a + H(b, c, d) + X[ 1] + 0xa4beea44, S31) + b; 273 d = rotateLeft(d + H(a, b, c) + X[ 4] + 0x4bdecfa9, S32) + a; 274 c = rotateLeft(c + H(d, a, b) + X[ 7] + 0xf6bb4b60, S33) + d; 275 b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c; 276 a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b; 277 d = rotateLeft(d + H(a, b, c) + X[ 0] + 0xeaa127fa, S32) + a; 278 c = rotateLeft(c + H(d, a, b) + X[ 3] + 0xd4ef3085, S33) + d; 279 b = rotateLeft(b + H(c, d, a) + X[ 6] + 0x04881d05, S34) + c; 280 a = rotateLeft(a + H(b, c, d) + X[ 9] + 0xd9d4d039, S31) + b; 281 d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a; 282 c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d; 283 b = rotateLeft(b + H(c, d, a) + X[ 2] + 0xc4ac5665, S34) + c; 284 285 // 286 // Round 4 - K cycle, 16 times. 287 // 288 a = rotateLeft(a + K(b, c, d) + X[ 0] + 0xf4292244, S41) + b; 289 d = rotateLeft(d + K(a, b, c) + X[ 7] + 0x432aff97, S42) + a; 290 c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d; 291 b = rotateLeft(b + K(c, d, a) + X[ 5] + 0xfc93a039, S44) + c; 292 a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b; 293 d = rotateLeft(d + K(a, b, c) + X[ 3] + 0x8f0ccc92, S42) + a; 294 c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d; 295 b = rotateLeft(b + K(c, d, a) + X[ 1] + 0x85845dd1, S44) + c; 296 a = rotateLeft(a + K(b, c, d) + X[ 8] + 0x6fa87e4f, S41) + b; 297 d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a; 298 c = rotateLeft(c + K(d, a, b) + X[ 6] + 0xa3014314, S43) + d; 299 b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c; 300 a = rotateLeft(a + K(b, c, d) + X[ 4] + 0xf7537e82, S41) + b; 301 d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a; 302 c = rotateLeft(c + K(d, a, b) + X[ 2] + 0x2ad7d2bb, S43) + d; 303 b = rotateLeft(b + K(c, d, a) + X[ 9] + 0xeb86d391, S44) + c; 304 305 H1 += a; 306 H2 += b; 307 H3 += c; 308 H4 += d; 309 310 // 311 // reset the offset and clean out the word buffer. 312 // 313 xOff = 0; 314 for (int i = 0; i != X.length; i++) 315 { 316 X[i] = 0; 317 } 318 } 319 }