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.security.DigestException; 23import java.security.MessageDigest; 24import java.security.NoSuchAlgorithmException; 25import java.security.NoSuchProviderException; 26import java.security.Provider; 27import java.security.Security; 28import java.util.ArrayList; 29import java.util.Arrays; 30import java.util.HashMap; 31import java.util.List; 32import java.util.Map; 33import java.util.Map.Entry; 34 35public class MessageDigest2Test extends junit.framework.TestCase { 36 37 private static final String MESSAGEDIGEST_ID = "MessageDigest."; 38 39 private Map<Provider, List<String>> digestAlgs = new HashMap<Provider, List<String>>(); 40 41 private static final byte[] AR1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 42 43 private static final byte[] AR2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 44 45 private static final String MESSAGE = "abc"; 46 47 private static final byte[] MESSAGE_DIGEST = { -87, -103, 62, 54, 71, 6, 48 -127, 106, -70, 62, 37, 113, 120, 80, -62, 108, -100, -48, -40, 49 -99, }; 50 51 private static final byte[] MESSAGE_DIGEST_63_As = { 3, -16, -97, 91, 21, 52 -118, 122, -116, -38, -39, 32, -67, -36, 41, -72, 28, 24, -91, 81, 53 -11, }; 54 55 private static final byte[] MESSAGE_DIGEST_64_As = { 0, -104, -70, -126, 56 75, 92, 22, 66, 123, -41, -95, 18, 42, 90, 68, 42, 37, -20, 100, 57 77, }; 58 59 private static final byte[] MESSAGE_DIGEST_65_As = { 17, 101, 83, 38, -57, 60 8, -41, 3, 25, -66, 38, 16, -24, -91, 125, -102, 91, -107, -99, 59, }; 61 62 /** 63 * java.security.MessageDigest#MessageDigest(java.lang.String) 64 */ 65 public void test_constructor() { 66 for (List<String> algorithms : digestAlgs.values()) { 67 for (String algorithm : algorithms) { 68 MessageDigestStub md = new MessageDigestStub(algorithm); 69 assertEquals(algorithm, md.getAlgorithm()); 70 assertEquals(0, md.getDigestLength()); 71 assertNull(md.getProvider()); 72 } 73 } 74 } 75 76 /** 77 * java.security.MessageDigest#clone() 78 */ 79 public void test_clone() throws Exception { 80 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 81 for (String algorithm : e.getValue()) { 82 MessageDigest d1 = MessageDigest.getInstance(algorithm, e.getKey().getName()); 83 for (byte b = 0; b < 84; b++) { 84 d1.update(b); 85 } 86 87 MessageDigest d2 = (MessageDigest) d1.clone(); 88 d1.update((byte) 1); 89 d2.update((byte) 1); 90 91 assertTrue("cloned hash differs from original for algorithm " + algorithm, 92 MessageDigest.isEqual(d1.digest(), d2.digest())); 93 } 94 } 95 } 96 97 private static final byte[] SHA_DATA_2 = { 70, -54, 124, 120, -29, 57, 56, 98 119, -108, -54, -97, -76, -97, -50, -63, -73, 2, 85, -53, -79, }; 99 100 private void testSerializationSHA_DATA_2(MessageDigest sha) throws Exception { 101 sha.reset(); 102 ByteArrayOutputStream out = new ByteArrayOutputStream(); 103 DataOutputStream output = new DataOutputStream(out); 104 105 // Made up data 106 output.writeUTF("tests.api.java.security.MessageDigestTest$InitializerFieldsTest3"); 107 output.writeInt(0); // class modifiers 108 output.writeUTF("java.io.Serializable"); // interfaces 109 110 // Fields 111 output.writeUTF("sub_toBeNotSerialized"); // name 112 output.writeInt(9); // modifiers 113 output.writeUTF("Ljava/lang/String;"); // signature 114 115 output.writeUTF("sub_toBeNotSerialized2"); // name 116 output.writeInt(9); // modifiers 117 output.writeUTF("Ljava/lang/String;"); // signature 118 119 output.writeUTF("sub_toBeSerialized"); // name 120 output.writeInt(1); // modifiers 121 output.writeUTF("Ljava/lang/String;"); // signature 122 123 output.writeUTF("sub_toBeSerialized3"); // name 124 output.writeInt(1); // modifiers 125 output.writeUTF("Ljava/lang/String;"); // signature 126 127 output.writeUTF("sub_toBeSerialized4"); // name 128 output.writeInt(1); // modifiers 129 output.writeUTF("Ljava/lang/String;"); // signature 130 131 output.writeUTF("sub_toBeSerialized5"); // name 132 output.writeInt(1); // modifiers 133 output.writeUTF("Ljava/lang/String;"); // signature 134 135 // clinit 136 output.writeUTF("<clinit>"); // name 137 output.writeInt(8); // modifiers 138 output.writeUTF("()V"); // signature 139 140 // constructors 141 output.writeUTF("<init>"); // name 142 output.writeInt(0); // modifiers 143 output.writeUTF("()V"); // signature 144 145 // methods 146 output.writeUTF("equals"); // name 147 output.writeInt(1); // modifiers 148 output.writeUTF("(Ljava.lang.Object;)Z"); // signature 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 } 156 157 private static final byte[] SHA_DATA_1 = { 90, 36, 111, 106, -32, 38, 4, 158 126, 21, -51, 107, 45, -64, -68, -109, 112, -31, -46, 34, 115, }; 159 160 private void testSerializationSHA_DATA_1(MessageDigest sha) throws Exception { 161 sha.reset(); 162 ByteArrayOutputStream out = new ByteArrayOutputStream(); 163 DataOutputStream output = new DataOutputStream(out); 164 165 // Made up data 166 output.writeUTF("tests.api.java.security.MessageDigestTest$OptionalDataNotRead"); 167 // name 168 output.writeInt(0); // class modifiers 169 output.writeUTF("java.io.Serializable"); // interfaces 170 171 // Fields 172 output.writeUTF("class$0"); // name 173 output.writeInt(8); // modifiers 174 output.writeUTF("Ljava/lang/Class;"); // signature 175 176 output.writeUTF("field1"); // name 177 output.writeInt(2); // modifiers 178 output.writeUTF("I"); // signature 179 180 output.writeUTF("field2"); // name 181 output.writeInt(2); // modifiers 182 output.writeUTF("I"); // signature 183 184 // clinit 185 output.writeUTF("<clinit>"); // name 186 output.writeInt(8); // modifiers 187 output.writeUTF("()V"); // signature 188 189 // constructors 190 output.writeUTF("<init>"); // name 191 output.writeInt(1); // modifiers 192 output.writeUTF("()V"); // signature 193 194 output.flush(); 195 byte[] data = out.toByteArray(); 196 byte[] hash = sha.digest(data); 197 assertTrue("SHA_DATA_1 NOT ok", Arrays.equals(hash, SHA_DATA_1)); 198 } 199 200 /** 201 * java.security.MessageDigest#digest() 202 */ 203 public void test_digest() throws Exception { 204 MessageDigest sha = MessageDigest.getInstance("SHA"); 205 assertNotNull(sha); 206 sha.update(MESSAGE.getBytes()); 207 byte[] digest = sha.digest(); 208 assertTrue("bug in SHA", MessageDigest.isEqual(digest, MESSAGE_DIGEST)); 209 210 sha.reset(); 211 for (int i = 0; i < 63; i++) { 212 // just under buffer capacity 213 sha.update((byte) 'a'); 214 } 215 digest = sha.digest(); 216 assertTrue("bug in SHA", MessageDigest.isEqual(digest, MESSAGE_DIGEST_63_As)); 217 218 sha.reset(); 219 for (int i = 0; i < 64; i++) { 220 // exact SHA buffer capacity 221 sha.update((byte) 'a'); 222 } 223 digest = sha.digest(); 224 assertTrue("bug in SHA", MessageDigest.isEqual(digest, MESSAGE_DIGEST_64_As)); 225 226 sha.reset(); 227 for (int i = 0; i < 65; i++) { 228 // just above SHA buffer capacity 229 sha.update((byte) 'a'); 230 } 231 digest = sha.digest(); 232 assertTrue("bug in SHA", MessageDigest.isEqual(digest, MESSAGE_DIGEST_65_As)); 233 234 testSerializationSHA_DATA_1(sha); 235 testSerializationSHA_DATA_2(sha); 236 } 237 238 /** 239 * java.security.MessageDigest#digest(byte[]) 240 */ 241 public void test_digest$B() throws Exception { 242 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 243 for (String algorithm : e.getValue()) { 244 MessageDigest digest = MessageDigest.getInstance(algorithm, e.getKey().getName()); 245 assertNotNull(digest); 246 digest.digest(AR1); 247 } 248 } 249 } 250 251 /** 252 * java.security.MessageDigest#digest(byte[], int, int) 253 */ 254 public void test_digest$BII() throws Exception { 255 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 256 for (String algorithm : e.getValue()) { 257 MessageDigest digest = MessageDigest.getInstance(algorithm, e.getKey().getName()); 258 assertNotNull(digest); 259 int len = digest.getDigestLength(); 260 byte[] digestBytes = new byte[len]; 261 digest.digest(digestBytes, 0, digestBytes.length); 262 } 263 try { 264 MessageDigest.getInstance("SHA").digest(new byte[] {}, Integer.MAX_VALUE, 755); 265 fail(); 266 } catch (IllegalArgumentException expected) { 267 } 268 } 269 } 270 271 /** 272 * java.security.MessageDigest#update(byte[], int, int) 273 */ 274 public void test_update$BII() throws Exception { 275 try { 276 MessageDigest.getInstance("SHA").update(new byte[] {}, 277 Integer.MAX_VALUE, Integer.MAX_VALUE); 278 fail(); 279 } catch (IllegalArgumentException expected) { 280 } 281 } 282 283 /** 284 * java.security.MessageDigest#getAlgorithm() 285 */ 286 public void test_getAlgorithm() throws Exception { 287 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 288 for (String algorithm : e.getValue()) { 289 MessageDigest md = MessageDigest.getInstance(algorithm, e.getKey().getName()); 290 assertEquals(algorithm, md.getAlgorithm()); 291 } 292 } 293 } 294 295 /** 296 * java.security.MessageDigest#getDigestLength() 297 */ 298 public void test_getDigestLength() throws Exception { 299 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 300 for (String algorithm : e.getValue()) { 301 MessageDigest md = MessageDigest.getInstance(algorithm, e.getKey().getName()); 302 assertTrue("length not ok", md.getDigestLength() > 0); 303 } 304 } 305 } 306 307 /** 308 * java.security.MessageDigest#getInstance(java.lang.String) 309 */ 310 public void test_getInstanceLjava_lang_String() throws Exception { 311 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 312 for (String algorithm : e.getValue()) { 313 MessageDigest md = MessageDigest.getInstance(algorithm); 314 assertNotNull(md); 315 } 316 } 317 318 try { 319 MessageDigest.getInstance("UnknownDigest"); 320 fail("expected NoSuchAlgorithmException"); 321 } catch (NoSuchAlgorithmException expected) { 322 } 323 } 324 325 /** 326 * java.security.MessageDigest#getInstance(java.lang.String, 327 * java.lang.String) 328 */ 329 public void test_getInstanceLjava_lang_StringLjava_lang_String() throws Exception { 330 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 331 for (String algorithm : e.getValue()) { 332 MessageDigest md = MessageDigest.getInstance(algorithm, e.getKey().getName()); 333 assertNotNull(md); 334 } 335 } 336 337 for (List<String> algorithms : digestAlgs.values()) { 338 for (String algorithm : algorithms) { 339 try { 340 MessageDigest.getInstance(algorithm, "UnknownProvider"); 341 fail("expected NoSuchProviderException"); 342 } catch (NoSuchProviderException expected) { 343 } 344 } 345 } 346 347 for (Provider provider : digestAlgs.keySet()) { 348 try { 349 MessageDigest.getInstance("UnknownDigest", provider.getName()); 350 fail("expected NoSuchAlgorithmException"); 351 } catch (NoSuchAlgorithmException expected) { 352 } 353 } 354 355 for (Provider provider : digestAlgs.keySet()) { 356 try { 357 MessageDigest.getInstance(null, provider.getName()); 358 fail("expected NullPointerException"); 359 } catch (NullPointerException expected) { 360 } 361 } 362 363 try { 364 MessageDigest.getInstance("AnyDigest", (String)null); 365 fail("expected IllegalArgumentException"); 366 } catch (IllegalArgumentException expected) { 367 } 368 } 369 370 /** 371 * java.security.MessageDigest#getInstance(java.lang.String, 372 * java.security.Provider) 373 */ 374 public void test_getInstanceLjava_lang_StringLjava_security_Provider() throws Exception { 375 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 376 for (String algorithm : e.getValue()) { 377 MessageDigest md = MessageDigest.getInstance(algorithm, e.getKey().getName()); 378 assertNotNull(md); 379 } 380 } 381 382 try { 383 MessageDigest.getInstance(null, new TestProvider()); 384 fail("expected NullPointerException"); 385 } catch (NullPointerException expected) { 386 } 387 388 try { 389 MessageDigest.getInstance("UnknownDigest", new TestProvider()); 390 fail("expected NoSuchAlgorithmException"); 391 } catch (NoSuchAlgorithmException expected) { 392 } 393 394 try { 395 MessageDigest.getInstance("AnyDigest", (Provider)null); 396 fail("expected IllegalArgumentException"); 397 } catch (IllegalArgumentException expected) { 398 } 399 } 400 401 /** 402 * java.security.MessageDigest#getProvider() 403 */ 404 public void test_getProvider() throws Exception { 405 for (Entry<Provider, List<String>> e : digestAlgs.entrySet()) { 406 for (String algorithm : e.getValue()) { 407 MessageDigest md = MessageDigest.getInstance(algorithm, e.getKey().getName()); 408 assertNotNull("provider is null", md.getProvider()); 409 } 410 } 411 } 412 413 /** 414 * java.security.MessageDigest#isEqual(byte[], byte[]) 415 */ 416 public void test_isEqual$B$B() { 417 assertTrue("isEqual is not correct", MessageDigest.isEqual(AR1, AR2)); 418 } 419 420 /** 421 * java.security.MessageDigest#toString() 422 */ 423 public void test_toString() throws Exception { 424 String str = MessageDigest.getInstance("SHA").toString(); 425 assertNotNull("toString is null", str); 426 } 427 428 protected void setUp() { 429 Provider[] providers = Security.getProviders("MessageDigest.SHA"); 430 for (Provider provider : providers) { 431 digestAlgs.put(provider, getDigestAlgorithms(provider)); 432 } 433 } 434 435 /* 436 * Returns the digest algorithms that the given provider supports. 437 */ 438 private List<String> getDigestAlgorithms(Provider provider) { 439 if (provider == null) { 440 fail("No digest algorithms were found"); 441 } 442 443 List<String> algs = new ArrayList<String>(); 444 for (Object key : provider.keySet()) { 445 String algorithm = (String) key; 446 if (algorithm.startsWith(MESSAGEDIGEST_ID) && !algorithm.contains(" ")) { 447 algs.add(algorithm.substring(MESSAGEDIGEST_ID.length())); 448 } 449 } 450 451 if (algs.size() == 0) { 452 fail("No digest algorithms were found"); 453 } 454 return algs; 455 } 456 457 private class MessageDigestStub extends MessageDigest { 458 public MessageDigestStub(String algorithm) { 459 super(algorithm); 460 } 461 462 public byte[] engineDigest() { 463 return null; 464 } 465 466 public void engineReset() { 467 468 } 469 470 public void engineUpdate(byte input) { 471 472 } 473 474 public void engineUpdate(byte[] input, int offset, int len) { 475 476 } 477 478 } 479 480 private static class TestProvider extends Provider { 481 482 protected TestProvider() { 483 super("TestProvider", 1.0, "INFO"); 484 485 } 486 487 } 488} 489