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