Source for gnu.java.security.hash.RipeMD128

   1: /* RipeMD128.java --
   2:    Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.java.security.hash;
  40: 
  41: import gnu.java.security.Registry;
  42: import gnu.java.security.util.Util;
  43: 
  44: /**
  45:  * RIPEMD-128 is a 128-bit message digest.
  46:  * <p>
  47:  * References:
  48:  * <ol>
  49:  *    <li><a href="http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html">
  50:  *    RIPEMD160</a>: A Strengthened Version of RIPEMD.<br>
  51:  *    Hans Dobbertin, Antoon Bosselaers and Bart Preneel.</li>
  52:  * </ol>
  53:  */
  54: public class RipeMD128
  55:     extends BaseHash
  56: {
  57:   private static final int BLOCK_SIZE = 64; // inner block size in bytes
  58: 
  59:   private static final String DIGEST0 = "CDF26213A150DC3ECB610F18F6B38B46";
  60: 
  61:   /** Constants for the transform method. */
  62:   // selection of message word
  63:   private static final int[] R = {
  64:        0,  1,  2,  3,  4,  5,  6, 7,  8, 9, 10, 11, 12, 13, 14, 15,
  65:        7,  4, 13,  1, 10,  6, 15, 3, 12, 0,  9,  5,  2, 14, 11,  8,
  66:        3, 10, 14,  4,  9, 15,  8, 1,  2, 7,  0,  6, 13, 11,  5, 12,
  67:        1,  9, 11, 10,  0,  8, 12, 4, 13, 3,  7, 15, 14,  5,  6,  2 };
  68: 
  69:   private static final int[] Rp = {
  70:        5, 14, 7, 0, 9,  2, 11,  4, 13,  6, 15,  8, 1, 10,  3, 12,
  71:        6, 11, 3, 7, 0, 13,  5, 10, 14, 15,  8, 12, 4,  9,  1,  2,
  72:       15,  5, 1, 3, 7, 14,  6,  9, 11,  8, 12,  2, 10, 0,  4, 13,
  73:        8,  6, 4, 1, 3, 11, 15,  0,  5, 12,  2, 13,  9, 7, 10, 14 };
  74: 
  75:   // amount for rotate left (rol)
  76:   private static final int[] S = {
  77:       11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
  78:        7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
  79:       11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
  80:       11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12 };
  81: 
  82:   private static final int[] Sp = {
  83:        8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
  84:        9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
  85:        9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
  86:       15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8 };
  87: 
  88:   /** caches the result of the correctness test, once executed. */
  89:   private static Boolean valid;
  90: 
  91:   /** 128-bit h0, h1, h2, h3 (interim result) */
  92:   private int h0, h1, h2, h3;
  93: 
  94:   /** 512 bits work buffer = 16 x 32-bit words */
  95:   private int[] X = new int[16];
  96: 
  97:   /** Trivial 0-arguments constructor. */
  98:   public RipeMD128()
  99:   {
 100:     super(Registry.RIPEMD128_HASH, 16, BLOCK_SIZE);
 101:   }
 102: 
 103:   /**
 104:    * Private constructor for cloning purposes.
 105:    *
 106:    * @param md the instance to clone.
 107:    */
 108:   private RipeMD128(RipeMD128 md)
 109:   {
 110:     this();
 111: 
 112:     this.h0 = md.h0;
 113:     this.h1 = md.h1;
 114:     this.h2 = md.h2;
 115:     this.h3 = md.h3;
 116:     this.count = md.count;
 117:     this.buffer = (byte[]) md.buffer.clone();
 118:   }
 119: 
 120:   public Object clone()
 121:   {
 122:     return new RipeMD128(this);
 123:   }
 124: 
 125:   protected void transform(byte[] in, int offset)
 126:   {
 127:     int A, B, C, D, Ap, Bp, Cp, Dp, T, s, i;
 128:     // encode 64 bytes from input block into an array of 16 unsigned integers.
 129:     for (i = 0; i < 16; i++)
 130:       X[i] = (in[offset++] & 0xFF)
 131:            | (in[offset++] & 0xFF) << 8
 132:            | (in[offset++] & 0xFF) << 16
 133:            |  in[offset++]         << 24;
 134:     A = Ap = h0;
 135:     B = Bp = h1;
 136:     C = Cp = h2;
 137:     D = Dp = h3;
 138:     for (i = 0; i < 16; i++) // rounds 0...15
 139:       {
 140:         s = S[i];
 141:         T = A + (B ^ C ^ D) + X[i];
 142:         A = D;
 143:         D = C;
 144:         C = B;
 145:         B = T << s | T >>> (32 - s);
 146: 
 147:         s = Sp[i];
 148:         T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x50A28BE6;
 149:         Ap = Dp;
 150:         Dp = Cp;
 151:         Cp = Bp;
 152:         Bp = T << s | T >>> (32 - s);
 153:       }
 154:     for (; i < 32; i++) // rounds 16...31
 155:       {
 156:         s = S[i];
 157:         T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999;
 158:         A = D;
 159:         D = C;
 160:         C = B;
 161:         B = T << s | T >>> (32 - s);
 162: 
 163:         s = Sp[i];
 164:         T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x5C4DD124;
 165:         Ap = Dp;
 166:         Dp = Cp;
 167:         Cp = Bp;
 168:         Bp = T << s | T >>> (32 - s);
 169:       }
 170:     for (; i < 48; i++) // rounds 32...47
 171:       {
 172:         s = S[i];
 173:         T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1;
 174:         A = D;
 175:         D = C;
 176:         C = B;
 177:         B = T << s | T >>> (32 - s);
 178: 
 179:         s = Sp[i];
 180:         T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x6D703EF3;
 181:         Ap = Dp;
 182:         Dp = Cp;
 183:         Cp = Bp;
 184:         Bp = T << s | T >>> (32 - s);
 185:       }
 186:     for (; i < 64; i++) // rounds 48...63
 187:       {
 188:         s = S[i];
 189:         T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC;
 190:         A = D;
 191:         D = C;
 192:         C = B;
 193:         B = T << s | T >>> (32 - s);
 194: 
 195:         s = Sp[i];
 196:         T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]];
 197:         Ap = Dp;
 198:         Dp = Cp;
 199:         Cp = Bp;
 200:         Bp = T << s | T >>> (32 - s);
 201:       }
 202:     T = h1 + C + Dp;
 203:     h1 = h2 + D + Ap;
 204:     h2 = h3 + A + Bp;
 205:     h3 = h0 + B + Cp;
 206:     h0 = T;
 207:   }
 208: 
 209:   protected byte[] padBuffer()
 210:   {
 211:     int n = (int)(count % BLOCK_SIZE);
 212:     int padding = (n < 56) ? (56 - n) : (120 - n);
 213:     byte[] result = new byte[padding + 8];
 214:     // padding is always binary 1 followed by binary 0s
 215:     result[0] = (byte) 0x80;
 216:     // save number of bits, casting the long to an array of 8 bytes
 217:     long bits = count << 3;
 218:     result[padding++] = (byte) bits;
 219:     result[padding++] = (byte)(bits >>> 8);
 220:     result[padding++] = (byte)(bits >>> 16);
 221:     result[padding++] = (byte)(bits >>> 24);
 222:     result[padding++] = (byte)(bits >>> 32);
 223:     result[padding++] = (byte)(bits >>> 40);
 224:     result[padding++] = (byte)(bits >>> 48);
 225:     result[padding  ] = (byte)(bits >>> 56);
 226:     return result;
 227:   }
 228: 
 229:   protected byte[] getResult()
 230:   {
 231:     return new byte[] {
 232:         (byte) h0, (byte)(h0 >>> 8), (byte)(h0 >>> 16), (byte)(h0 >>> 24),
 233:         (byte) h1, (byte)(h1 >>> 8), (byte)(h1 >>> 16), (byte)(h1 >>> 24),
 234:         (byte) h2, (byte)(h2 >>> 8), (byte)(h2 >>> 16), (byte)(h2 >>> 24),
 235:         (byte) h3, (byte)(h3 >>> 8), (byte)(h3 >>> 16), (byte)(h3 >>> 24)
 236:     };
 237:   }
 238: 
 239:   protected void resetContext()
 240:   {
 241:     // magic RIPEMD128 initialisation constants
 242:     h0 = 0x67452301;
 243:     h1 = 0xEFCDAB89;
 244:     h2 = 0x98BADCFE;
 245:     h3 = 0x10325476;
 246:   }
 247: 
 248:   public boolean selfTest()
 249:   {
 250:     if (valid == null)
 251:       {
 252:         String d = Util.toString(new RipeMD128().digest());
 253:         valid = Boolean.valueOf(DIGEST0.equals(d));
 254:       }
 255:     return valid.booleanValue();
 256:   }
 257: }