Source code: com/ssttr/crypto/MessageDigest.java
1 /*
2 * @(#)MessageDigest.java 1.7 95/08/15
3 *
4 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and distribute this software
7 * and its documentation for NON-COMMERCIAL purposes and without
8 * fee is hereby granted provided that this copyright notice
9 * appears in all copies. Please refer to the file "copyright.html"
10 * for further important copyright and licensing information.
11 *
12 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
13 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
14 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
16 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
17 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
18 *
19 * Updated to JDK 1.0.2 levels by Chuck McManis
20 *
21 * This file was obtained from: http://www.mcmanis.com/~cmcmanis/java/src/util/crypt/MessageDigest.java
22 * More information can be found here: http://www.mcmanis.com/~cmcmanis/java/
23 */
24
25 package com.ssttr.crypto;
26
27 import java.util.*;
28 import java.io.ByteArrayOutputStream;
29 import java.io.PrintStream;
30 import java.io.InputStream;
31
32
33 /**
34 * The MessageDigest class defines a general class for computing digest
35 * functions. It is defined as an abstract class that is subclassed by
36 * message digest algorithms. In this way the PKCS classes can be built
37 * to take a MessageDigest object without needing to know what 'kind'
38 * of message digest they are computing.
39 *
40 * This class defines the standard functions that all message digest
41 * algorithms share, and ways to put all Java fundamental types into
42 * the digest. It does not define methods for digestifying either
43 * arbitrary objects or arrays of objects however.
44 *
45 * @version 5 Oct 1996, 1.8
46 * @author Chuck McManis
47 */
48 public abstract class MessageDigest
49 {
50
51 /** the actual digest bits. */
52 public byte digestBits[];
53
54 /** status of the digest */
55 public boolean digestValid;
56
57 /**
58 * This function is used to initialize any internal digest
59 * variables or parameters.
60 */
61 public abstract void init();
62
63 /**
64 * The basic unit of digestifying is the byte. This method is
65 * defined by the particular algorithim's subclass for that
66 * algorithim. Subsequent versions of this method defined here
67 * decompose the basic type into bytes and call this function.
68 * If special processing is needed for a particular type your
69 * subclass should override the method for that type.
70 */
71 public abstract void update(byte aValue);
72
73 /**
74 * Add a boolean to the digest.
75 */
76 public synchronized void update(boolean aValue) {
77 byte b;
78
79 if (aValue)
80 b = 1;
81 else
82 b = 0;
83 update(b);
84 }
85
86 /**
87 * Add a short value to the digest.
88 */
89 public synchronized void update(short aValue) {
90 byte b1, b2;
91
92 b1 = (byte)((aValue >>> 8) & 0xff);
93 b2 = (byte)(aValue & 0xff);
94 update(b1);
95 update(b2);
96 }
97
98 /**
99 * Add an integer value to the digest.
100 */
101 public synchronized void update(int aValue) {
102 byte b;
103
104 for (int i = 3; i >= 0; i--) {
105 b = (byte)((aValue >>> (i * 8)) & 0xff);
106 update(b);
107 }
108 }
109
110 /**
111 * Add a long to the digest.
112 */
113 public synchronized void update(long aValue) {
114 byte b;
115
116 for (int i = 7; i >= 0; i--) {
117 b = (byte)((aValue >>> (i * 8)) & 0xff);
118 update(b);
119 }
120 }
121
122 /**
123 * Add specific bytes to the digest.
124 */
125 public synchronized void update(byte input[], int offset, int len) {
126 for (int i = 0; i < len; i++) {
127 update(input[i+offset]);
128 }
129 }
130
131 /**
132 * Add an array of bytes to the digest.
133 */
134 public synchronized void update(byte input[]) {
135 update(input, 0, input.length);
136 }
137
138 /**
139 * Add an array of shorts to the digest.
140 */
141 public synchronized void update(short input[]) {
142 for (int i = 0; i < input.length; i++) {
143 update(input[i]);
144 }
145 }
146
147 /**
148 * Add an array of integers to the digest.
149 */
150 public synchronized void update(int input[]) {
151 for (int i = 0; i < input.length; i++) {
152 update(input[i]);
153 }
154 }
155
156 /**
157 * Add an array of longs to the digest.
158 */
159 public synchronized void update(long input[]) {
160 for (int i = 0; i < input.length; i++) {
161 update(input[i]);
162 }
163 }
164
165 /**
166 * Add the bytes in the String 'input' to the current digest.
167 * Note that the string characters are treated as unicode chars
168 * of 16 bits each. To digestify ISO-Latin1 strings (ASCII) use
169 * the updateASCII() method.
170 */
171 public void update(String input) {
172 int i, len;
173 short x;
174
175 len = input.length();
176 for (i = 0; i < len; i++) {
177 x = (short) input.charAt(i);
178 update(x);
179 }
180 }
181
182 /**
183 * Treat the string as a sequence of ISO-Latin1 (8 bit) characters.
184 */
185 public void updateASCII(String input) {
186 int i, len;
187 byte x;
188
189 len = input.length();
190 for (i = 0; i < len; i++) {
191 x = (byte) (input.charAt(i) & 0xff);
192 update(x);
193 }
194 }
195
196 /**
197 * Read a stream and update a digest until the
198 * stream sends an EOF.
199 */
200 public void update(InputStream in) {
201 byte b;
202
203 try {
204 while ((b = (byte) in.read()) != -1)
205 update(b);
206 } catch (Exception e) { }
207 }
208
209 /**
210 * Perform the final computations and cleanup.
211 */
212 public abstract void finish();
213
214 /**
215 * Complete digest computation on an array of bytes.
216 */
217 public void computeDigest(byte source[]) {
218 init();
219 update(source);
220 finish();
221 }
222
223 public void computeDigest(InputStream in) {
224 init();
225 update(in);
226 finish();
227 }
228
229 /**
230 * helper function that prints unsigned two character hex digits.
231 */
232 private void hexDigit(PrintStream p, byte x) {
233 char c;
234
235 c = (char) ((x >> 4) & 0xf);
236 if (c > 9)
237 c = (char) ((c - 10) + 'a');
238 else
239 c = (char) (c + '0');
240 p.write(c);
241 c = (char) (x & 0xf);
242 if (c > 9)
243 c = (char)((c-10) + 'a');
244 else
245 c = (char)(c + '0');
246 p.write(c);
247 }
248
249 /**
250 * Return a string representation of this object.
251 */
252 public String toString() {
253 ByteArrayOutputStream ou = new ByteArrayOutputStream();
254 PrintStream p = new PrintStream(ou);
255
256 p.print(this.getClass().getName()+" Message Digest ");
257 if (digestValid) {
258 p.print("<");
259 for(int i = 0; i < digestBits.length; i++)
260 hexDigit(p, digestBits[i]);
261 p.print(">");
262 } else {
263 p.print("<incomplete>");
264 }
265 p.println();
266 return (ou.toString());
267 }
268
269 public String getDigest()
270 {
271 if (digestValid) {
272 StringBuffer b = new StringBuffer();
273 for(int i = 0; i < digestBits.length; i++)
274 b.append( (char)digestBits[i] );
275 return b.toString();
276 }
277 else
278 {
279 return null;
280 }
281 }
282
283 public byte[] getDigestBytes()
284 {
285 if(digestValid) {
286 return digestBits;
287 }
288 else
289 {
290 return null;
291 }
292 }
293
294 public String getDigestHex()
295 {
296 ByteArrayOutputStream ou = new ByteArrayOutputStream();
297 PrintStream p = new PrintStream(ou);
298
299 if (digestValid) {
300 for(int i = 0; i < digestBits.length; i++)
301 hexDigit(p, digestBits[i]);
302 } else {
303 return null;
304 }
305 return (ou.toString());
306 }
307
308 /**
309 * Compare two digests for equality. Simple byte compare.
310 */
311 public static boolean isEqual(byte digesta[], byte digestb[]) {
312 int i;
313
314 if (digesta.length != digestb.length)
315 return (false);
316
317 for (i = 0; i < digesta.length; i++) {
318 if (digesta[i] != digestb[i]) {
319 return (false);
320 }
321 }
322 return (true);
323 }
324
325 /**
326 * Non static version that compares this digest to one passed.
327 */
328 public boolean isEqual(byte otherDigest[]) {
329 return (MessageDigest.isEqual(digestBits, otherDigest));
330 }
331
332 /**
333 * Return a string that represents the algorithim of this
334 * message digest.
335 */
336 public abstract String getAlg();
337
338 static byte testdata[];
339
340 public static void benchmark(MessageDigest md) {
341 Random rnd = new Random(); // use random data
342 testdata = new byte[16384];
343 long times[] = new long[14];
344 double rates[] = new double[14];
345
346 for (int i = 0; i < testdata.length; i++) {
347 testdata[i] = (byte) (rnd.nextInt() >>> 8);
348 }
349 System.out.println("Benchmarking "+md.getAlg());
350 System.out.println("Bytes Time (mS) Rate (Bytes/Sec)");
351 for (int i = 1; i < 10; i++) {
352 long t1 = System.currentTimeMillis();
353 md.init();
354 for (int k = 0; k < i; k++)
355 md.update(testdata);
356 md.finish();
357 times[i] = System.currentTimeMillis() - t1;
358 rates[i] = ((double) (i*testdata.length) * 1000.0)/ (double) times[i];
359 System.out.println((i*testdata.length)+"\t"+times[i]+"\t"+rates[i]);
360 }
361 System.out.println("Done.");
362 }
363
364 }