1 /* RipeMD160.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-160 is a 160-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 RipeMD160 55 extends BaseHash 56 { 57 private static final int BLOCK_SIZE = 64; // inner block size in bytes 58 59 private static final String DIGEST0 = "9C1185A5C5E9FC54612808977EE8F548B2258D31"; 60 61 // selection of message word 62 private static final int[] R = { 63 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 64 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 65 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 66 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 67 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 }; 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 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 }; 75 76 // amount for rotate left (rol) 77 private static final int[] S = { 78 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 79 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 80 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 81 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 82 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 }; 83 84 private static final int[] Sp = { 85 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 86 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 87 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 88 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 89 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 }; 90 91 /** caches the result of the correctness test, once executed. */ 92 private static Boolean valid; 93 94 /** 160-bit h0, h1, h2, h3, h4 (interim result) */ 95 private int h0, h1, h2, h3, h4; 96 97 /** 512 bits work buffer = 16 x 32-bit words */ 98 private int[] X = new int[16]; 99 100 /** Trivial 0-arguments constructor. */ RipeMD160()101 public RipeMD160() 102 { 103 super(Registry.RIPEMD160_HASH, 20, BLOCK_SIZE); 104 } 105 106 /** 107 * Private constructor for cloning purposes. 108 * 109 * @param md the instance to clone. 110 */ RipeMD160(RipeMD160 md)111 private RipeMD160(RipeMD160 md) 112 { 113 this(); 114 115 this.h0 = md.h0; 116 this.h1 = md.h1; 117 this.h2 = md.h2; 118 this.h3 = md.h3; 119 this.h4 = md.h4; 120 this.count = md.count; 121 this.buffer = (byte[]) md.buffer.clone(); 122 } 123 clone()124 public Object clone() 125 { 126 return (new RipeMD160(this)); 127 } 128 transform(byte[] in, int offset)129 protected void transform(byte[] in, int offset) 130 { 131 int A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, T, s, i; 132 // encode 64 bytes from input block into an array of 16 unsigned integers 133 for (i = 0; i < 16; i++) 134 X[i] = (in[offset++] & 0xFF) 135 | (in[offset++] & 0xFF) << 8 136 | (in[offset++] & 0xFF) << 16 137 | in[offset++] << 24; 138 A = Ap = h0; 139 B = Bp = h1; 140 C = Cp = h2; 141 D = Dp = h3; 142 E = Ep = h4; 143 for (i = 0; i < 16; i++) // rounds 0...15 144 { 145 s = S[i]; 146 T = A + (B ^ C ^ D) + X[i]; 147 A = E; 148 E = D; 149 D = C << 10 | C >>> 22; 150 C = B; 151 B = (T << s | T >>> (32 - s)) + A; 152 153 s = Sp[i]; 154 T = Ap + (Bp ^ (Cp | ~Dp)) + X[Rp[i]] + 0x50A28BE6; 155 Ap = Ep; 156 Ep = Dp; 157 Dp = Cp << 10 | Cp >>> 22; 158 Cp = Bp; 159 Bp = (T << s | T >>> (32 - s)) + Ap; 160 } 161 for (; i < 32; i++) // rounds 16...31 162 { 163 s = S[i]; 164 T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999; 165 A = E; 166 E = D; 167 D = C << 10 | C >>> 22; 168 C = B; 169 B = (T << s | T >>> (32 - s)) + A; 170 171 s = Sp[i]; 172 T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x5C4DD124; 173 Ap = Ep; 174 Ep = Dp; 175 Dp = Cp << 10 | Cp >>> 22; 176 Cp = Bp; 177 Bp = (T << s | T >>> (32 - s)) + Ap; 178 } 179 for (; i < 48; i++) // rounds 32...47 180 { 181 s = S[i]; 182 T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1; 183 A = E; 184 E = D; 185 D = C << 10 | C >>> 22; 186 C = B; 187 B = (T << s | T >>> (32 - s)) + A; 188 189 s = Sp[i]; 190 T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x6D703EF3; 191 Ap = Ep; 192 Ep = Dp; 193 Dp = Cp << 10 | Cp >>> 22; 194 Cp = Bp; 195 Bp = (T << s | T >>> (32 - s)) + Ap; 196 } 197 for (; i < 64; i++) // rounds 48...63 198 { 199 s = S[i]; 200 T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC; 201 A = E; 202 E = D; 203 D = C << 10 | C >>> 22; 204 C = B; 205 B = (T << s | T >>> (32 - s)) + A; 206 207 s = Sp[i]; 208 T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x7A6D76E9; 209 Ap = Ep; 210 Ep = Dp; 211 Dp = Cp << 10 | Cp >>> 22; 212 Cp = Bp; 213 Bp = (T << s | T >>> (32 - s)) + Ap; 214 } 215 for (; i < 80; i++) // rounds 64...79 216 { 217 s = S[i]; 218 T = A + (B ^ (C | ~D)) + X[R[i]] + 0xA953FD4E; 219 A = E; 220 E = D; 221 D = C << 10 | C >>> 22; 222 C = B; 223 B = (T << s | T >>> (32 - s)) + A; 224 225 s = Sp[i]; 226 T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]]; 227 Ap = Ep; 228 Ep = Dp; 229 Dp = Cp << 10 | Cp >>> 22; 230 Cp = Bp; 231 Bp = (T << s | T >>> (32 - s)) + Ap; 232 } 233 T = h1 + C + Dp; 234 h1 = h2 + D + Ep; 235 h2 = h3 + E + Ap; 236 h3 = h4 + A + Bp; 237 h4 = h0 + B + Cp; 238 h0 = T; 239 } 240 padBuffer()241 protected byte[] padBuffer() 242 { 243 int n = (int)(count % BLOCK_SIZE); 244 int padding = (n < 56) ? (56 - n) : (120 - n); 245 byte[] result = new byte[padding + 8]; 246 // padding is always binary 1 followed by binary 0s 247 result[0] = (byte) 0x80; 248 // save number of bits, casting the long to an array of 8 bytes 249 long bits = count << 3; 250 result[padding++] = (byte) bits; 251 result[padding++] = (byte)(bits >>> 8); 252 result[padding++] = (byte)(bits >>> 16); 253 result[padding++] = (byte)(bits >>> 24); 254 result[padding++] = (byte)(bits >>> 32); 255 result[padding++] = (byte)(bits >>> 40); 256 result[padding++] = (byte)(bits >>> 48); 257 result[padding ] = (byte)(bits >>> 56); 258 return result; 259 } 260 getResult()261 protected byte[] getResult() 262 { 263 return new byte[] { 264 (byte) h0, (byte)(h0 >>> 8), (byte)(h0 >>> 16), (byte)(h0 >>> 24), 265 (byte) h1, (byte)(h1 >>> 8), (byte)(h1 >>> 16), (byte)(h1 >>> 24), 266 (byte) h2, (byte)(h2 >>> 8), (byte)(h2 >>> 16), (byte)(h2 >>> 24), 267 (byte) h3, (byte)(h3 >>> 8), (byte)(h3 >>> 16), (byte)(h3 >>> 24), 268 (byte) h4, (byte)(h4 >>> 8), (byte)(h4 >>> 16), (byte)(h4 >>> 24) 269 }; 270 } 271 resetContext()272 protected void resetContext() 273 { 274 // magic RIPEMD160 initialisation constants 275 h0 = 0x67452301; 276 h1 = 0xEFCDAB89; 277 h2 = 0x98BADCFE; 278 h3 = 0x10325476; 279 h4 = 0xC3D2E1F0; 280 } 281 selfTest()282 public boolean selfTest() 283 { 284 if (valid == null) 285 { 286 String d = Util.toString(new RipeMD160().digest()); 287 valid = Boolean.valueOf(DIGEST0.equals(d)); 288 } 289 return valid.booleanValue(); 290 } 291 } 292