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. */ RipeMD128()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 */ RipeMD128(RipeMD128 md)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 clone()120 public Object clone() 121 { 122 return new RipeMD128(this); 123 } 124 transform(byte[] in, int offset)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 padBuffer()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 getResult()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 resetContext()239 protected void resetContext() 240 { 241 // magic RIPEMD128 initialisation constants 242 h0 = 0x67452301; 243 h1 = 0xEFCDAB89; 244 h2 = 0x98BADCFE; 245 h3 = 0x10325476; 246 } 247 selfTest()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 } 258