MessageDigest2Test.java revision 561ee011997c6c2f1befbfaa9d5f0a99771c1d63
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.harmony.security.tests.java.security;
19
20import java.io.ByteArrayOutputStream;
21import java.io.DataOutputStream;
22import java.io.IOException;
23import java.io.UnsupportedEncodingException;
24import java.security.DigestException;
25import java.security.MessageDigest;
26import java.security.NoSuchAlgorithmException;
27import java.security.NoSuchProviderException;
28import java.security.Provider;
29import java.security.Security;
30import java.util.Arrays;
31import java.util.Enumeration;
32import java.util.Vector;
33
34public class MessageDigest2Test extends junit.framework.TestCase {
35
36	private static final String MESSAGEDIGEST_ID = "MessageDigest.";
37
38	private String[] digestAlgs = null;
39
40	private String providerName = null;
41
42	private static final byte[] AR1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
43
44	private static final byte[] AR2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
45
46	private static final String MESSAGE = "abc";
47
48	private static final byte[] MESSAGE_DIGEST = { -87, -103, 62, 54, 71, 6,
49			-127, 106, -70, 62, 37, 113, 120, 80, -62, 108, -100, -48, -40,
50			-99, };
51
52	private static final byte[] MESSAGE_DIGEST_63_As = { 3, -16, -97, 91, 21,
53			-118, 122, -116, -38, -39, 32, -67, -36, 41, -72, 28, 24, -91, 81,
54			-11, };
55
56	private static final byte[] MESSAGE_DIGEST_64_As = { 0, -104, -70, -126,
57			75, 92, 22, 66, 123, -41, -95, 18, 42, 90, 68, 42, 37, -20, 100,
58			77, };
59
60	private static final byte[] MESSAGE_DIGEST_65_As = { 17, 101, 83, 38, -57,
61			8, -41, 3, 25, -66, 38, 16, -24, -91, 125, -102, 91, -107, -99, 59, };
62
63	/**
64	 * @tests java.security.MessageDigest#clone()
65	 */
66	public void test_clone() {
67		for (int i = 0; i < digestAlgs.length; i++) {
68			try {
69				MessageDigest d1 = MessageDigest.getInstance(digestAlgs[i],
70						providerName);
71				for (byte b = 0; b < 84; b++) {
72					d1.update(b);
73				}
74
75				MessageDigest d2 = (MessageDigest) d1.clone();
76				d1.update((byte) 1);
77				d2.update((byte) 1);
78
79				assertTrue("cloned hash differs from original for algorithm "
80						+ digestAlgs[i], MessageDigest.isEqual(d1.digest(), d2
81						.digest()));
82			} catch (CloneNotSupportedException e) {
83				// Expected - a Signature may not be cloneable
84			} catch (NoSuchAlgorithmException e) {
85				fail("getInstance did not find algorithm " + digestAlgs[i]);
86			} catch (NoSuchProviderException e) {
87				fail("getInstance did not find provider " + providerName);
88			}
89		}
90	}
91
92	private static final byte[] SHA_DATA_2 = { 70, -54, 124, 120, -29, 57, 56,
93			119, -108, -54, -97, -76, -97, -50, -63, -73, 2, 85, -53, -79, };
94
95	private void testSerializationSHA_DATA_2(MessageDigest sha) {
96		try {
97			sha.reset();
98			ByteArrayOutputStream out = new ByteArrayOutputStream();
99			DataOutputStream output = new DataOutputStream(out);
100			// -----------------------------------------------------------------------
101
102			// Made up data
103			output
104					.writeUTF("tests.api.java.security.MessageDigestTest$InitializerFieldsTest3");
105			output.writeInt(0); // class modifiers
106			output.writeUTF("java.io.Serializable"); // interfaces
107
108			// Fields
109			output.writeUTF("sub_toBeNotSerialized"); // name
110			output.writeInt(9); // modifiers
111			output.writeUTF("Ljava/lang/String;"); // signature
112
113			output.writeUTF("sub_toBeNotSerialized2"); // name
114			output.writeInt(9); // modifiers
115			output.writeUTF("Ljava/lang/String;"); // signature
116
117			output.writeUTF("sub_toBeSerialized"); // name
118			output.writeInt(1); // modifiers
119			output.writeUTF("Ljava/lang/String;"); // signature
120
121			output.writeUTF("sub_toBeSerialized3"); // name
122			output.writeInt(1); // modifiers
123			output.writeUTF("Ljava/lang/String;"); // signature
124
125			output.writeUTF("sub_toBeSerialized4"); // name
126			output.writeInt(1); // modifiers
127			output.writeUTF("Ljava/lang/String;"); // signature
128
129			output.writeUTF("sub_toBeSerialized5"); // name
130			output.writeInt(1); // modifiers
131			output.writeUTF("Ljava/lang/String;"); // signature
132
133			// clinit
134			output.writeUTF("<clinit>"); // name
135			output.writeInt(8); // modifiers
136			output.writeUTF("()V"); // signature
137
138			// constructors
139			output.writeUTF("<init>"); // name
140			output.writeInt(0); // modifiers
141			output.writeUTF("()V"); // signature
142
143			// methods
144			output.writeUTF("equals"); // name
145			output.writeInt(1); // modifiers
146			output.writeUTF("(Ljava.lang.Object;)Z"); // signature
147
148			// -----------------------------------------------------------------------
149
150			output.flush();
151
152			byte[] data = out.toByteArray();
153			byte[] hash = sha.digest(data);
154			assertTrue("SHA_DATA_2 NOT ok", Arrays.equals(hash, SHA_DATA_2));
155		} catch (IOException e) {
156			fail("SHA_DATA_2 NOT ok");
157		}
158	}
159
160	private static final byte[] SHA_DATA_1 = { 90, 36, 111, 106, -32, 38, 4,
161			126, 21, -51, 107, 45, -64, -68, -109, 112, -31, -46, 34, 115, };
162
163	private void testSerializationSHA_DATA_1(MessageDigest sha) {
164		try {
165			sha.reset();
166			ByteArrayOutputStream out = new ByteArrayOutputStream();
167			DataOutputStream output = new DataOutputStream(out);
168			// -----------------------------------------------------------------------
169
170			// Made up data
171			output
172					.writeUTF("tests.api.java.security.MessageDigestTest$OptionalDataNotRead");
173			// name
174			output.writeInt(0); // class modifiers
175			output.writeUTF("java.io.Serializable"); // interfaces
176
177			// Fields
178			output.writeUTF("class$0"); // name
179			output.writeInt(8); // modifiers
180			output.writeUTF("Ljava/lang/Class;"); // signature
181
182			output.writeUTF("field1"); // name
183			output.writeInt(2); // modifiers
184			output.writeUTF("I"); // signature
185
186			output.writeUTF("field2"); // name
187			output.writeInt(2); // modifiers
188			output.writeUTF("I"); // signature
189
190			// clinit
191			output.writeUTF("<clinit>"); // name
192			output.writeInt(8); // modifiers
193			output.writeUTF("()V"); // signature
194
195			// constructors
196			output.writeUTF("<init>"); // name
197			output.writeInt(1); // modifiers
198			output.writeUTF("()V"); // signature
199			// -----------------------------------------------------------------------
200
201			output.flush();
202			byte[] data = out.toByteArray();
203			byte[] hash = sha.digest(data);
204			assertTrue("SHA_DATA_1 NOT ok", Arrays.equals(hash, SHA_DATA_1));
205		} catch (IOException e) {
206			fail("SHA_DATA_1 NOT ok");
207		}
208	}
209
210	/**
211	 * @throws UnsupportedEncodingException
212	 * @tests java.security.MessageDigest#digest()
213	 */
214	public void test_digest() throws UnsupportedEncodingException {
215		MessageDigest sha = null;
216		try {
217			sha = MessageDigest.getInstance("SHA");
218			assertNotNull(sha);
219		} catch (NoSuchAlgorithmException e) {
220			fail("getInstance did not find algorithm");
221		}
222		sha.update(MESSAGE.getBytes("UTF-8"));
223		byte[] digest = sha.digest();
224		assertTrue("bug in SHA", MessageDigest.isEqual(digest, MESSAGE_DIGEST));
225
226		sha.reset();
227		for (int i = 0; i < 63; i++) {
228			// just under buffer capacity
229			sha.update((byte) 'a');
230		}
231		digest = sha.digest();
232		assertTrue("bug in SHA", MessageDigest.isEqual(digest,
233				MESSAGE_DIGEST_63_As));
234
235		sha.reset();
236		for (int i = 0; i < 64; i++) {
237			// exact SHA buffer capacity
238			sha.update((byte) 'a');
239		}
240		digest = sha.digest();
241		assertTrue("bug in SHA", MessageDigest.isEqual(digest,
242				MESSAGE_DIGEST_64_As));
243
244		sha.reset();
245		for (int i = 0; i < 65; i++) {
246			// just above SHA buffer capacity
247			sha.update((byte) 'a');
248		}
249		digest = sha.digest();
250		assertTrue("bug in SHA", MessageDigest.isEqual(digest,
251				MESSAGE_DIGEST_65_As));
252
253		testSerializationSHA_DATA_1(sha);
254		testSerializationSHA_DATA_2(sha);
255	}
256
257	/**
258	 * @tests java.security.MessageDigest#digest(byte[])
259	 */
260	public void test_digest$B() {
261		for (int i = 0; i < digestAlgs.length; i++) {
262			try {
263				MessageDigest digest = MessageDigest.getInstance(digestAlgs[i],
264						providerName);
265				assertNotNull(digest);
266				digest.digest(AR1);
267			} catch (NoSuchAlgorithmException e) {
268				fail("getInstance did not find algorithm " + digestAlgs[i]);
269			} catch (NoSuchProviderException e) {
270				fail("getInstance did not find provider " + providerName);
271			}
272		}
273	}
274
275	/**
276	 * @tests java.security.MessageDigest#digest(byte[], int, int)
277	 */
278	public void test_digest$BII() {
279		for (int i = 0; i < digestAlgs.length; i++) {
280			try {
281				MessageDigest digest = MessageDigest.getInstance(digestAlgs[i],
282						providerName);
283				assertNotNull(digest);
284				int len = digest.getDigestLength();
285				byte[] digestBytes = new byte[len];
286				digest.digest(digestBytes, 0, digestBytes.length);
287			} catch (NoSuchAlgorithmException e) {
288				fail("getInstance did not find algorithm " + digestAlgs[i]);
289			} catch (NoSuchProviderException e) {
290				fail("getInstance did not find provider " + providerName);
291			} catch (DigestException e) {
292				fail("digest caused exception for algorithm " + digestAlgs[i]
293						+ " : " + e);
294			}
295		}
296        try {
297            MessageDigest.getInstance("SHA").digest(new byte[] {}, Integer.MAX_VALUE, 755);
298        } catch (NoSuchAlgorithmException e) {
299        	//allowed
300        } catch (DigestException e) {
301        	//allowed
302        } catch (IllegalArgumentException e) {
303        	//expected
304        }
305	}
306
307	/**
308	 * @tests java.security.MessageDigest#update(byte[], int, int)
309	 */
310	public void test_update$BII() {
311        try {
312        	MessageDigest.getInstance("SHA").update(new byte[] {},Integer.MAX_VALUE,Integer.MAX_VALUE);
313		} catch (NoSuchAlgorithmException e) {
314        	//allowed
315        } catch (IllegalArgumentException e) {
316        	//expected
317        }
318	}
319
320	/**
321	 * @tests java.security.MessageDigest#getAlgorithm()
322	 */
323	public void test_getAlgorithm() {
324		for (int i = 0; i < digestAlgs.length; i++) {
325			try {
326				String alg = MessageDigest.getInstance(digestAlgs[i],
327						providerName).getAlgorithm();
328				assertTrue("getAlgorithm ok", alg.equals(digestAlgs[i]));
329			} catch (NoSuchAlgorithmException e) {
330				fail("getInstance did not find algorithm " + digestAlgs[i]);
331			} catch (NoSuchProviderException e) {
332				fail("getInstance did not find provider " + providerName);
333			}
334		}
335	}
336
337	/**
338	 * @tests java.security.MessageDigest#getDigestLength()
339	 */
340	public void test_getDigestLength() {
341		for (int i = 0; i < digestAlgs.length; i++) {
342			try {
343				int len = MessageDigest
344						.getInstance(digestAlgs[i], providerName)
345						.getDigestLength();
346				assertTrue("length not ok", len > 0);
347			} catch (NoSuchAlgorithmException e) {
348				fail("getInstance did not find algorithm " + digestAlgs[i]);
349			} catch (NoSuchProviderException e) {
350				fail("getInstance did not find provider " + providerName);
351			}
352		}// end for
353	}
354
355	/**
356	 * @tests java.security.MessageDigest#getInstance(java.lang.String)
357	 */
358	public void test_getInstanceLjava_lang_String() {
359		for (int i = 0; i < digestAlgs.length; i++) {
360			try {
361				MessageDigest.getInstance(digestAlgs[i]);
362			} catch (NoSuchAlgorithmException e) {
363				fail("getInstance did not find algorithm " + digestAlgs[i]);
364			}
365		}
366	}
367
368	/**
369	 * @tests java.security.MessageDigest#getInstance(java.lang.String,
370	 *        java.lang.String)
371	 */
372	public void test_getInstanceLjava_lang_StringLjava_lang_String() {
373		for (int i = 0; i < digestAlgs.length; i++) {
374			try {
375				MessageDigest.getInstance(digestAlgs[i], providerName);
376			} catch (NoSuchAlgorithmException e) {
377				fail("getInstance did not find algorithm " + digestAlgs[i]);
378			} catch (NoSuchProviderException e) {
379				fail("getInstance did not find provider " + providerName);
380			}
381		}
382	}
383
384	/**
385	 * @tests java.security.MessageDigest#getProvider()
386	 */
387	public void test_getProvider() {
388		for (int i = 0; i < digestAlgs.length; i++) {
389			try {
390				Provider p = MessageDigest.getInstance(digestAlgs[i],
391						providerName).getProvider();
392				assertNotNull("provider is null", p);
393			} catch (NoSuchAlgorithmException e) {
394				fail("getInstance did not find algorithm " + digestAlgs[i]);
395			} catch (NoSuchProviderException e) {
396				fail("getInstance did not find provider " + providerName);
397			}
398		}
399	}
400
401	/**
402	 * @tests java.security.MessageDigest#isEqual(byte[], byte[])
403	 */
404	public void test_isEqual$B$B() {
405		assertTrue("isEqual is not correct", MessageDigest.isEqual(AR1, AR2));
406	}
407
408	/**
409	 * @tests java.security.MessageDigest#toString()
410	 */
411	public void test_toString() {
412		try {
413			String str = MessageDigest.getInstance("SHA").toString();
414			assertNotNull("toString is null", str);
415		} catch (NoSuchAlgorithmException e) {
416			fail("getInstance did not find algorithm");
417		}
418	}
419
420	protected void setUp() {
421		if (digestAlgs == null) {
422			Provider[] providers = Security.getProviders("MessageDigest.SHA");
423			if (providers == null) {
424				fail("No providers available for test");
425			}
426
427			// Arbitrarily select the first available provider
428			providerName = providers[0].getName();
429			digestAlgs = getDigestAlgorithms(providerName);
430			if (digestAlgs == null || digestAlgs.length == 0) {
431				fail("No digest algorithms were found");
432			}
433		}
434	}
435
436	/*
437	 * Returns the digest algorithms that the given provider supports.
438	 */
439	private String[] getDigestAlgorithms(String providerName) {
440		Vector algs = new Vector();
441
442		Provider provider = Security.getProvider(providerName);
443		if (provider == null)
444			return new String[0];
445		Enumeration e = provider.keys();
446		while (e.hasMoreElements()) {
447			String algorithm = (String) e.nextElement();
448			if (algorithm.startsWith(MESSAGEDIGEST_ID) && !algorithm.contains(" ")) {
449				algs.addElement(algorithm.substring(MESSAGEDIGEST_ID.length()));
450			}
451		}// end while
452
453		return (String[]) algs.toArray(new String[algs.size()]);
454	}
455}