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 MD4 as RFC 1320 by R. Rivest, MIT Laboratory for 023 * Computer Science and RSA Data Security, Inc. 024 * <p> 025 * <b>NOTE</b>: This algorithm is only included for backwards compatability 026 * with legacy applications, it's not secure, don't use it for anything new! 027 */ 028 public class MD4Digest 029 extends GeneralDigest 030 { 031 private static final int DIGEST_LENGTH = 16; 032 033 private int H1, H2, H3, H4; // IV's 034 035 private int[] X = new int[16]; 036 private int xOff; 037 038 /** 039 * Standard constructor 040 */ 041 public MD4Digest() 042 { 043 reset(); 044 } 045 046 /** 047 * Copy constructor. This will copy the state of the provided 048 * message digest. 049 */ 050 public MD4Digest(MD4Digest t) 051 { 052 super(t); 053 054 H1 = t.H1; 055 H2 = t.H2; 056 H3 = t.H3; 057 H4 = t.H4; 058 059 System.arraycopy(t.X, 0, X, 0, t.X.length); 060 xOff = t.xOff; 061 } 062 063 public String getAlgorithmName() 064 { 065 return "MD4"; 066 } 067 068 public int getDigestSize() 069 { 070 return DIGEST_LENGTH; 071 } 072 073 protected void processWord( 074 byte[] in, 075 int inOff) 076 { 077 X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) 078 | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 079 080 if (xOff == 16) 081 { 082 processBlock(); 083 } 084 } 085 086 protected void processLength( 087 long bitLength) 088 { 089 if (xOff > 14) 090 { 091 processBlock(); 092 } 093 094 X[14] = (int)(bitLength & 0xffffffff); 095 X[15] = (int)(bitLength >>> 32); 096 } 097 098 private void unpackWord( 099 int word, 100 byte[] out, 101 int outOff) 102 { 103 out[outOff] = (byte)word; 104 out[outOff + 1] = (byte)(word >>> 8); 105 out[outOff + 2] = (byte)(word >>> 16); 106 out[outOff + 3] = (byte)(word >>> 24); 107 } 108 109 public int doFinal( 110 byte[] out, 111 int outOff) 112 { 113 finish(); 114 115 unpackWord(H1, out, outOff); 116 unpackWord(H2, out, outOff + 4); 117 unpackWord(H3, out, outOff + 8); 118 unpackWord(H4, out, outOff + 12); 119 120 reset(); 121 122 return DIGEST_LENGTH; 123 } 124 125 /** 126 * reset the chaining variables to the IV values. 127 */ 128 public void reset() 129 { 130 super.reset(); 131 132 H1 = 0x67452301; 133 H2 = 0xefcdab89; 134 H3 = 0x98badcfe; 135 H4 = 0x10325476; 136 137 xOff = 0; 138 139 for (int i = 0; i != X.length; i++) 140 { 141 X[i] = 0; 142 } 143 } 144 145 // 146 // round 1 left rotates 147 // 148 private static final int S11 = 3; 149 private static final int S12 = 7; 150 private static final int S13 = 11; 151 private static final int S14 = 19; 152 153 // 154 // round 2 left rotates 155 // 156 private static final int S21 = 3; 157 private static final int S22 = 5; 158 private static final int S23 = 9; 159 private static final int S24 = 13; 160 161 // 162 // round 3 left rotates 163 // 164 private static final int S31 = 3; 165 private static final int S32 = 9; 166 private static final int S33 = 11; 167 private static final int S34 = 15; 168 169 /* 170 * rotate int x left n bits. 171 */ 172 private int rotateLeft( 173 int x, 174 int n) 175 { 176 return (x << n) | (x >>> (32 - n)); 177 } 178 179 /* 180 * F, G, H and I are the basic MD4 functions. 181 */ 182 private int F( 183 int u, 184 int v, 185 int w) 186 { 187 return (u & v) | (~u & w); 188 } 189 190 private int G( 191 int u, 192 int v, 193 int w) 194 { 195 return (u & v) | (u & w) | (v & w); 196 } 197 198 private int H( 199 int u, 200 int v, 201 int w) 202 { 203 return u ^ v ^ w; 204 } 205 206 protected void processBlock() 207 { 208 int a = H1; 209 int b = H2; 210 int c = H3; 211 int d = H4; 212 213 // 214 // Round 1 - F cycle, 16 times. 215 // 216 a = rotateLeft(a + F(b, c, d) + X[ 0], S11); 217 d = rotateLeft(d + F(a, b, c) + X[ 1], S12); 218 c = rotateLeft(c + F(d, a, b) + X[ 2], S13); 219 b = rotateLeft(b + F(c, d, a) + X[ 3], S14); 220 a = rotateLeft(a + F(b, c, d) + X[ 4], S11); 221 d = rotateLeft(d + F(a, b, c) + X[ 5], S12); 222 c = rotateLeft(c + F(d, a, b) + X[ 6], S13); 223 b = rotateLeft(b + F(c, d, a) + X[ 7], S14); 224 a = rotateLeft(a + F(b, c, d) + X[ 8], S11); 225 d = rotateLeft(d + F(a, b, c) + X[ 9], S12); 226 c = rotateLeft(c + F(d, a, b) + X[10], S13); 227 b = rotateLeft(b + F(c, d, a) + X[11], S14); 228 a = rotateLeft(a + F(b, c, d) + X[12], S11); 229 d = rotateLeft(d + F(a, b, c) + X[13], S12); 230 c = rotateLeft(c + F(d, a, b) + X[14], S13); 231 b = rotateLeft(b + F(c, d, a) + X[15], S14); 232 233 // 234 // Round 2 - G cycle, 16 times. 235 // 236 a = rotateLeft(a + G(b, c, d) + X[ 0] + 0x5a827999, S21); 237 d = rotateLeft(d + G(a, b, c) + X[ 4] + 0x5a827999, S22); 238 c = rotateLeft(c + G(d, a, b) + X[ 8] + 0x5a827999, S23); 239 b = rotateLeft(b + G(c, d, a) + X[12] + 0x5a827999, S24); 240 a = rotateLeft(a + G(b, c, d) + X[ 1] + 0x5a827999, S21); 241 d = rotateLeft(d + G(a, b, c) + X[ 5] + 0x5a827999, S22); 242 c = rotateLeft(c + G(d, a, b) + X[ 9] + 0x5a827999, S23); 243 b = rotateLeft(b + G(c, d, a) + X[13] + 0x5a827999, S24); 244 a = rotateLeft(a + G(b, c, d) + X[ 2] + 0x5a827999, S21); 245 d = rotateLeft(d + G(a, b, c) + X[ 6] + 0x5a827999, S22); 246 c = rotateLeft(c + G(d, a, b) + X[10] + 0x5a827999, S23); 247 b = rotateLeft(b + G(c, d, a) + X[14] + 0x5a827999, S24); 248 a = rotateLeft(a + G(b, c, d) + X[ 3] + 0x5a827999, S21); 249 d = rotateLeft(d + G(a, b, c) + X[ 7] + 0x5a827999, S22); 250 c = rotateLeft(c + G(d, a, b) + X[11] + 0x5a827999, S23); 251 b = rotateLeft(b + G(c, d, a) + X[15] + 0x5a827999, S24); 252 253 // 254 // Round 3 - H cycle, 16 times. 255 // 256 a = rotateLeft(a + H(b, c, d) + X[ 0] + 0x6ed9eba1, S31); 257 d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x6ed9eba1, S32); 258 c = rotateLeft(c + H(d, a, b) + X[ 4] + 0x6ed9eba1, S33); 259 b = rotateLeft(b + H(c, d, a) + X[12] + 0x6ed9eba1, S34); 260 a = rotateLeft(a + H(b, c, d) + X[ 2] + 0x6ed9eba1, S31); 261 d = rotateLeft(d + H(a, b, c) + X[10] + 0x6ed9eba1, S32); 262 c = rotateLeft(c + H(d, a, b) + X[ 6] + 0x6ed9eba1, S33); 263 b = rotateLeft(b + H(c, d, a) + X[14] + 0x6ed9eba1, S34); 264 a = rotateLeft(a + H(b, c, d) + X[ 1] + 0x6ed9eba1, S31); 265 d = rotateLeft(d + H(a, b, c) + X[ 9] + 0x6ed9eba1, S32); 266 c = rotateLeft(c + H(d, a, b) + X[ 5] + 0x6ed9eba1, S33); 267 b = rotateLeft(b + H(c, d, a) + X[13] + 0x6ed9eba1, S34); 268 a = rotateLeft(a + H(b, c, d) + X[ 3] + 0x6ed9eba1, S31); 269 d = rotateLeft(d + H(a, b, c) + X[11] + 0x6ed9eba1, S32); 270 c = rotateLeft(c + H(d, a, b) + X[ 7] + 0x6ed9eba1, S33); 271 b = rotateLeft(b + H(c, d, a) + X[15] + 0x6ed9eba1, S34); 272 273 H1 += a; 274 H2 += b; 275 H3 += c; 276 H4 += d; 277 278 // 279 // reset the offset and clean out the word buffer. 280 // 281 xOff = 0; 282 for (int i = 0; i != X.length; i++) 283 { 284 X[i] = 0; 285 } 286 } 287 }