%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.java.security.MD5 |
|
|
1 | package org.apache.java.security; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2005 The Apache Software Foundation. |
|
5 | * |
|
6 | * Licensed under the Apache License, Version 2.0 (the "License") |
|
7 | * you may not use this file except in compliance with the License. |
|
8 | * You may obtain a copy of the License at |
|
9 | * |
|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 | * |
|
12 | * Unless required by applicable law or agreed to in writing, software |
|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 | * See the License for the specific language governing permissions and |
|
16 | * limitations under the License. |
|
17 | */ |
|
18 | ||
19 | /** |
|
20 | * This class implements the Message Digest 5 algorithm (MD5) as |
|
21 | * defined in RFC-1321. |
|
22 | * |
|
23 | * <p><b>Note:</b> even if standard Java 1.1 APIs already provide a |
|
24 | * MD5 implementation, this class is used on those Java runtime |
|
25 | * environments (like Kaffe) where the package |
|
26 | * <code>java.security</code> is highly improbable to be found. |
|
27 | * |
|
28 | * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> |
|
29 | * @version $Id: MD5.java 264148 2005-08-29 14:21:04Z henning $ |
|
30 | * @deprecated Use the java.security package. |
|
31 | */ |
|
32 | public final class MD5 |
|
33 | extends MessageDigest |
|
34 | { |
|
35 | private long counter; |
|
36 | private int reminder; |
|
37 | private byte buffer[]; |
|
38 | private int state[]; |
|
39 | private int x[]; |
|
40 | ||
41 | /*********************** MD5 Functions ***********************/ |
|
42 | ||
43 | // 16 * 4 bytes |
|
44 | 0 | static byte padding[] = |
45 | { |
|
46 | (byte) 0x80, |
|
47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
48 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
50 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
|
51 | }; |
|
52 | ||
53 | /*********************** Self Test ***********************/ |
|
54 | ||
55 | 0 | private static String[] messages = |
56 | { |
|
57 | "", |
|
58 | "a", |
|
59 | "abc", |
|
60 | "message digest", |
|
61 | "abcdefghijklmnopqrstuvwxyz", |
|
62 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", |
|
63 | "12345678901234567890123456789012345678901234567890123456789012345678901234567890", |
|
64 | }; |
|
65 | ||
66 | 0 | private static String[] digests = |
67 | { |
|
68 | "d41d8cd98f00b204e9800998ecf8427e", |
|
69 | "0cc175b9c0f1b6a831c399e269772661", |
|
70 | "900150983cd24fb0d6963f7d28e17f72", |
|
71 | "f96b697d7cb7938d525a2f31aaf161d0", |
|
72 | "c3fcd3d76192e4007dfb496cca67e13b", |
|
73 | "d174ab98d277d9f5a5611c2c9f419d9f", |
|
74 | "57edf4a22be3c955ac49da2e2107b67a", |
|
75 | }; |
|
76 | ||
77 | ||
78 | /** |
|
79 | * Creates the algorithm and reset its state. |
|
80 | */ |
|
81 | public MD5() |
|
82 | { |
|
83 | 0 | super(); |
84 | 0 | } |
85 | ||
86 | /** |
|
87 | * Append another block of specified length to the message |
|
88 | * starting at the given offset. |
|
89 | * |
|
90 | * @param block A byte[]. |
|
91 | * @param offset An int. |
|
92 | * @param length An int. |
|
93 | */ |
|
94 | public void append(byte[] block, |
|
95 | int offset, |
|
96 | int length) |
|
97 | { |
|
98 | while (true) |
|
99 | { |
|
100 | 0 | if (length >= reminder) |
101 | { |
|
102 | 0 | System.arraycopy(block, offset, buffer, |
103 | (int) (counter & 63L), reminder); |
|
104 | 0 | transform(buffer); |
105 | 0 | counter += reminder; |
106 | 0 | offset += reminder; |
107 | 0 | length -= reminder; |
108 | 0 | reminder = 64; |
109 | } |
|
110 | else |
|
111 | { |
|
112 | 0 | System.arraycopy(block, offset, buffer, |
113 | (int) (counter & 63L), length); |
|
114 | 0 | counter += length; |
115 | 0 | reminder -= length; |
116 | 0 | break; |
117 | } |
|
118 | } |
|
119 | 0 | } |
120 | ||
121 | /*********************** Byte/Int utilities ***********************/ |
|
122 | ||
123 | /** |
|
124 | * Converts a 64-byte array into a 16-int array. |
|
125 | * |
|
126 | * @param in A byte[]. |
|
127 | * @param out An int[]. |
|
128 | */ |
|
129 | private static void byte2int(byte[] in, |
|
130 | int[] out) |
|
131 | { |
|
132 | 0 | for (int inpos = 0, outpos = 0; outpos < 16; outpos++) |
133 | { |
|
134 | 0 | out[outpos] = ((((int) (in[inpos++] & 0xff))) | |
135 | (((int) (in[inpos++] & 0xff)) << 8) | |
|
136 | (((int) (in[inpos++] & 0xff)) << 16) | |
|
137 | (((int) (in[inpos++] & 0xff)) << 24)); |
|
138 | } |
|
139 | 0 | } |
140 | ||
141 | /** |
|
142 | * Appends a message block with specified length starting from the |
|
143 | * given offset, and return its message digest. |
|
144 | * |
|
145 | * @param block A byte[]. |
|
146 | * @param offset An int. |
|
147 | * @param length An int. |
|
148 | */ |
|
149 | public byte[] digest(byte[] block, |
|
150 | int offset, |
|
151 | int length) |
|
152 | { |
|
153 | 0 | this.append(block, offset, length); |
154 | ||
155 | 0 | byte[] bits = toBytes(counter << 3); |
156 | 0 | byte[] digest = new byte[16]; |
157 | ||
158 | 0 | if (reminder > 8) |
159 | { |
|
160 | 0 | append(padding, 0, reminder - 8); |
161 | } |
|
162 | else |
|
163 | { |
|
164 | 0 | append(padding, 0, 64 + (reminder - 8)); |
165 | } |
|
166 | ||
167 | 0 | append(bits, 0, 8); |
168 | ||
169 | 0 | int2byte(state, digest); |
170 | ||
171 | 0 | this.reset(); |
172 | 0 | return digest; |
173 | } |
|
174 | ||
175 | /* |
|
176 | * Method F. |
|
177 | * |
|
178 | * @param x An int. |
|
179 | * @param y An int. |
|
180 | * @param z An int. |
|
181 | * @return An int. |
|
182 | */ |
|
183 | static private int F(class="keyword">int x, |
|
184 | int y, |
|
185 | int z) |
|
186 | { |
|
187 | 0 | return (z ^ (x & (y^z))); |
188 | } |
|
189 | ||
190 | /* |
|
191 | * Method FF. |
|
192 | * |
|
193 | * @param a An int. |
|
194 | * @param b An int. |
|
195 | * @param c An int. |
|
196 | * @param d An int. |
|
197 | * @param x An int. |
|
198 | * @param s An int. |
|
199 | * @param ac An int. |
|
200 | * @return An int. |
|
201 | */ |
|
202 | static private int FF(class="keyword">int a, |
|
203 | int b, |
|
204 | int c, |
|
205 | int d, |
|
206 | int x, |
|
207 | int s, |
|
208 | int ac) |
|
209 | { |
|
210 | 0 | a += x + ac + F(b,c,d); |
211 | 0 | a = (a << s | a >>> -s); |
212 | 0 | return a + b; |
213 | } |
|
214 | ||
215 | /* |
|
216 | * Method G. |
|
217 | * |
|
218 | * @param x An int. |
|
219 | * @param y An int. |
|
220 | * @param z An int. |
|
221 | * @return An int. |
|
222 | */ |
|
223 | static private int G(class="keyword">int x, |
|
224 | int y, |
|
225 | int z) |
|
226 | { |
|
227 | 0 | return (y ^ (z & (x^y))); |
228 | } |
|
229 | ||
230 | /* |
|
231 | * Method GG. |
|
232 | * |
|
233 | * @param a An int. |
|
234 | * @param b An int. |
|
235 | * @param c An int. |
|
236 | * @param d An int. |
|
237 | * @param x An int. |
|
238 | * @param s An int. |
|
239 | * @param ac An int. |
|
240 | * @return An int. |
|
241 | */ |
|
242 | static private int GG(class="keyword">int a, |
|
243 | int b, |
|
244 | int c, |
|
245 | int d, |
|
246 | int x, |
|
247 | int s, |
|
248 | int ac) |
|
249 | { |
|
250 | 0 | a += x + ac + G(b,c,d); |
251 | 0 | a = (a << s | a >>> -s); |
252 | 0 | return a + b; |
253 | } |
|
254 | ||
255 | /* |
|
256 | * Method H. |
|
257 | * |
|
258 | * @param x An int. |
|
259 | * @param y An int. |
|
260 | * @param z An int. |
|
261 | * @return An int. |
|
262 | */ |
|
263 | static private int H(class="keyword">int x, |
|
264 | int y, |
|
265 | int z) |
|
266 | { |
|
267 | 0 | return (x ^ y ^ z); |
268 | } |
|
269 | ||
270 | /* |
|
271 | * Method HH. |
|
272 | * |
|
273 | * @param a An int. |
|
274 | * @param b An int. |
|
275 | * @param c An int. |
|
276 | * @param d An int. |
|
277 | * @param x An int. |
|
278 | * @param s An int. |
|
279 | * @param ac An int. |
|
280 | * @return An int. |
|
281 | */ |
|
282 | static private int HH(class="keyword">int a, |
|
283 | int b, |
|
284 | int c, |
|
285 | int d, |
|
286 | int x, |
|
287 | int s, |
|
288 | int ac) |
|
289 | { |
|
290 | 0 | a += x + ac + H(b,c,d); |
291 | 0 | a = (a << s | a >>> -s); |
292 | 0 | return a + b; |
293 | } |
|
294 | ||
295 | /* |
|
296 | * Method I. |
|
297 | * |
|
298 | * @param x An int. |
|
299 | * @param y An int. |
|
300 | * @param z An int. |
|
301 | * @return An int. |
|
302 | */ |
|
303 | static private int I(class="keyword">int x, |
|
304 | int y, |
|
305 | int z) |
|
306 | { |
|
307 | 0 | return (y ^ (x | ~z)); |
308 | } |
|
309 | ||
310 | /* |
|
311 | * Method II. |
|
312 | * |
|
313 | * @param a An int. |
|
314 | * @param b An int. |
|
315 | * @param c An int. |
|
316 | * @param d An int. |
|
317 | * @param x An int. |
|
318 | * @param s An int. |
|
319 | * @param ac An int. |
|
320 | * @return An int. |
|
321 | */ |
|
322 | static private int II(class="keyword">int a, |
|
323 | int b, |
|
324 | int c, |
|
325 | int d, |
|
326 | int x, |
|
327 | int s, |
|
328 | int ac) |
|
329 | { |
|
330 | 0 | a += x + ac + I(b,c,d); |
331 | 0 | a = (a << s | a >>> -s); |
332 | 0 | return a + b; |
333 | } |
|
334 | ||
335 | /** |
|
336 | * Converts a 4-int array into a 16-byte array. |
|
337 | * |
|
338 | * @param in An int[]. |
|
339 | * @param out A byte[]. |
|
340 | */ |
|
341 | private static void int2byte(class="keyword">int[] in, |
|
342 | byte[] out) |
|
343 | { |
|
344 | 0 | for (int inpos = 0, outpos = 0; inpos < 4; inpos++) |
345 | { |
|
346 | 0 | out[outpos++] = (byte) (in[inpos] & 0xff); |
347 | 0 | out[outpos++] = (byte) ((in[inpos] >>> 8) & 0xff); |
348 | 0 | out[outpos++] = (byte) ((in[inpos] >>> 16) & 0xff); |
349 | 0 | out[outpos++] = (byte) ((in[inpos] >>> 24) & 0xff); |
350 | } |
|
351 | 0 | } |
352 | ||
353 | /* |
|
354 | * Main routine, for testing purposes only. |
|
355 | * |
|
356 | * @param ignored A String[] with the command line arguments. |
|
357 | */ |
|
358 | public static final void main(String[] ignored) |
|
359 | { |
|
360 | 0 | MD5 md5 = new MD5(); |
361 | ||
362 | 0 | for (int i = 0; i < messages.length; i++) |
363 | { |
|
364 | 0 | String digest = org.apache.java.lang.Bytes.toString( |
365 | md5.digest(messages[i].getBytes())); |
|
366 | 0 | System.out.println("Computed: " + digest); |
367 | 0 | System.out.println("Correct: " + digests[i]); |
368 | 0 | if (digest.equalsIgnoreCase(digests[i])) |
369 | { |
|
370 | 0 | System.out.println("Test " + i + " passed."); |
371 | } |
|
372 | else |
|
373 | { |
|
374 | 0 | System.out.println("Test " + i + " failed."); |
375 | } |
|
376 | } |
|
377 | 0 | } |
378 | ||
379 | /** |
|
380 | * Resets the state of the class. <b>Beware</b>: calling this |
|
381 | * method erases all data previously inserted. |
|
382 | */ |
|
383 | public void reset() |
|
384 | { |
|
385 | 0 | buffer = new byte[64]; |
386 | 0 | state = new int[4]; |
387 | 0 | x = new int[16]; |
388 | ||
389 | 0 | state[0] = 0x67452301; |
390 | 0 | state[1] = 0xefcdab89; |
391 | 0 | state[2] = 0x98badcfe; |
392 | 0 | state[3] = 0x10325476; |
393 | ||
394 | 0 | counter = 0; |
395 | 0 | reminder = 64; |
396 | 0 | } |
397 | ||
398 | /** |
|
399 | * Converts a long to a 8-byte array using low order first. |
|
400 | * |
|
401 | * @param n A long. |
|
402 | * @return A byte[]. |
|
403 | */ |
|
404 | public static byte[] toBytes(long n) |
|
405 | { |
|
406 | 0 | byte[] b = new byte[8]; |
407 | ||
408 | 0 | b[0] = (byte) (n); |
409 | 0 | n >>>= 8; |
410 | 0 | b[1] = (byte) (n); |
411 | 0 | n >>>= 8; |
412 | 0 | b[2] = (byte) (n); |
413 | 0 | n >>>= 8; |
414 | 0 | b[3] = (byte) (n); |
415 | 0 | n >>>= 8; |
416 | 0 | b[4] = (byte) (n); |
417 | 0 | n >>>= 8; |
418 | 0 | b[5] = (byte) (n); |
419 | 0 | n >>>= 8; |
420 | 0 | b[6] = (byte) (n); |
421 | 0 | n >>>= 8; |
422 | 0 | b[7] = (byte) (n); |
423 | ||
424 | 0 | return b; |
425 | } |
|
426 | ||
427 | /* |
|
428 | * TODO: Document. |
|
429 | * |
|
430 | * @param buffer A byte[]. |
|
431 | */ |
|
432 | private void transform(byte[] buffer) |
|
433 | { |
|
434 | int a, b, c, d; |
|
435 | ||
436 | 0 | byte2int(buffer, x); |
437 | ||
438 | 0 | a = state[0]; |
439 | 0 | b = state[1]; |
440 | 0 | c = state[2]; |
441 | 0 | d = state[3]; |
442 | ||
443 | 0 | a = FF(a, b, c, d, x[ 0], 7, 0xd76aa478); |
444 | 0 | d = FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); |
445 | 0 | c = FF(c, d, a, b, x[ 2], 17, 0x242070db); |
446 | 0 | b = FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); |
447 | 0 | a = FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); |
448 | 0 | d = FF(d, a, b, c, x[ 5], 12, 0x4787c62a); |
449 | 0 | c = FF(c, d, a, b, x[ 6], 17, 0xa8304613); |
450 | 0 | b = FF(b, c, d, a, x[ 7], 22, 0xfd469501); |
451 | 0 | a = FF(a, b, c, d, x[ 8], 7, 0x698098d8); |
452 | 0 | d = FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); |
453 | 0 | c = FF(c, d, a, b, x[10], 17, 0xffff5bb1); |
454 | 0 | b = FF(b, c, d, a, x[11], 22, 0x895cd7be); |
455 | 0 | a = FF(a, b, c, d, x[12], 7, 0x6b901122); |
456 | 0 | d = FF(d, a, b, c, x[13], 12, 0xfd987193); |
457 | 0 | c = FF(c, d, a, b, x[14], 17, 0xa679438e); |
458 | 0 | b = FF(b, c, d, a, x[15], 22, 0x49b40821); |
459 | ||
460 | 0 | a = GG(a, b, c, d, x[ 1], 5, 0xf61e2562); |
461 | 0 | d = GG(d, a, b, c, x[ 6], 9, 0xc040b340); |
462 | 0 | c = GG(c, d, a, b, x[11], 14, 0x265e5a51); |
463 | 0 | b = GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); |
464 | 0 | a = GG(a, b, c, d, x[ 5], 5, 0xd62f105d); |
465 | 0 | d = GG(d, a, b, c, x[10], 9, 0x2441453); |
466 | 0 | c = GG(c, d, a, b, x[15], 14, 0xd8a1e681); |
467 | 0 | b = GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); |
468 | 0 | a = GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); |
469 | 0 | d = GG(d, a, b, c, x[14], 9, 0xc33707d6); |
470 | 0 | c = GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); |
471 | 0 | b = GG(b, c, d, a, x[ 8], 20, 0x455a14ed); |
472 | 0 | a = GG(a, b, c, d, x[13], 5, 0xa9e3e905); |
473 | 0 | d = GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); |
474 | 0 | c = GG(c, d, a, b, x[ 7], 14, 0x676f02d9); |
475 | 0 | b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); |
476 | ||
477 | 0 | a = HH(a, b, c, d, x[ 5], 4, 0xfffa3942); |
478 | 0 | d = HH(d, a, b, c, x[ 8], 11, 0x8771f681); |
479 | 0 | c = HH(c, d, a, b, x[11], 16, 0x6d9d6122); |
480 | 0 | b = HH(b, c, d, a, x[14], 23, 0xfde5380c); |
481 | 0 | a = HH(a, b, c, d, x[ 1], 4, 0xa4beea44); |
482 | 0 | d = HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); |
483 | 0 | c = HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); |
484 | 0 | b = HH(b, c, d, a, x[10], 23, 0xbebfbc70); |
485 | 0 | a = HH(a, b, c, d, x[13], 4, 0x289b7ec6); |
486 | 0 | d = HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); |
487 | 0 | c = HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); |
488 | 0 | b = HH(b, c, d, a, x[ 6], 23, 0x4881d05); |
489 | 0 | a = HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); |
490 | 0 | d = HH(d, a, b, c, x[12], 11, 0xe6db99e5); |
491 | 0 | c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8); |
492 | 0 | b = HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); |
493 | ||
494 | 0 | a = II(a, b, c, d, x[ 0], 6, 0xf4292244); |
495 | 0 | d = II(d, a, b, c, x[ 7], 10, 0x432aff97); |
496 | 0 | c = II(c, d, a, b, x[14], 15, 0xab9423a7); |
497 | 0 | b = II(b, c, d, a, x[ 5], 21, 0xfc93a039); |
498 | 0 | a = II(a, b, c, d, x[12], 6, 0x655b59c3); |
499 | 0 | d = II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); |
500 | 0 | c = II(c, d, a, b, x[10], 15, 0xffeff47d); |
501 | 0 | b = II(b, c, d, a, x[ 1], 21, 0x85845dd1); |
502 | 0 | a = II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); |
503 | 0 | d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0); |
504 | 0 | c = II(c, d, a, b, x[ 6], 15, 0xa3014314); |
505 | 0 | b = II(b, c, d, a, x[13], 21, 0x4e0811a1); |
506 | 0 | a = II(a, b, c, d, x[ 4], 6, 0xf7537e82); |
507 | 0 | d = II(d, a, b, c, x[11], 10, 0xbd3af235); |
508 | 0 | c = II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); |
509 | 0 | b = II(b, c, d, a, x[ 9], 21, 0xeb86d391); |
510 | ||
511 | 0 | state[0] += a; |
512 | 0 | state[1] += b; |
513 | 0 | state[2] += c; |
514 | 0 | state[3] += d; |
515 | 0 | } |
516 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |