1package org.apache.harmony.security.tests.java.security; 2 3import dalvik.annotation.TestLevel; 4import dalvik.annotation.TestTargetClass; 5import dalvik.annotation.TestTargetNew; 6 7import junit.framework.TestCase; 8 9import java.lang.reflect.Constructor; 10import java.lang.reflect.InvocationTargetException; 11import java.security.InvalidKeyException; 12import java.security.Key; 13import java.security.KeyFactory; 14import java.security.KeyFactorySpi; 15import java.security.NoSuchAlgorithmException; 16import java.security.NoSuchProviderException; 17import java.security.PrivateKey; 18import java.security.Provider; 19import java.security.PublicKey; 20import java.security.Security; 21import java.security.spec.DSAPublicKeySpec; 22import java.security.spec.InvalidKeySpecException; 23import java.security.spec.KeySpec; 24import java.util.Arrays; 25 26@TestTargetClass(KeyFactory.class) 27public class KeyFactoryTest extends TestCase { 28 29 Provider provider; 30 boolean exceptionThrown; 31 32 Provider existingProvider; 33 34 @Override 35 protected void setUp() throws Exception { 36 super.setUp(); 37 exceptionThrown = false; 38 39 Provider[] providers = Security.getProviders(); 40 if (providers.length == 0) { 41 fail("no providers found"); 42 } 43 44 existingProvider = providers[0]; 45 46 provider = new TestKeyFactoryProvider(); 47 Security.addProvider(provider); 48 } 49 50 @Override 51 protected void tearDown() throws Exception { 52 super.tearDown(); 53 Security.removeProvider(provider.getName()); 54 } 55 56 @SuppressWarnings("unchecked") 57 @TestTargetNew( 58 level=TestLevel.COMPLETE, 59 method="getInstance", 60 args={String.class} 61 ) 62 public void testGetInstanceString() { 63 try { 64 KeyFactory factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME); 65 assertNotNull(factory); 66 } catch (NoSuchAlgorithmException e) { 67 fail("unexpected exception: " + e); 68 } 69 70 String[] parameters = { 71 "UnknownKeyFactory", 72 null 73 }; 74 75 Class[] exceptions = { 76 NoSuchAlgorithmException.class, 77 NullPointerException.class 78 }; 79 80 for (int i = 0; i < parameters.length; i++) { 81 String algorithm = parameters[i]; 82 exceptionThrown = false; 83 String message = "getInstance(" + (algorithm == null ? "null" : "\"" + algorithm + "\"") + ")"; 84 try { 85 KeyFactory.getInstance(algorithm); 86 } catch (Exception e) { 87 checkException(message, e, exceptions[i]); 88 } finally { 89 checkException(message, null, exceptions[i]); 90 } 91 } 92 93 } 94 95 @SuppressWarnings("unchecked") 96 @TestTargetNew( 97 level=TestLevel.COMPLETE, 98 method="getInstance", 99 args={String.class, String.class} 100 ) 101 public void testGetInstanceStringString() { 102 try { 103 KeyFactory factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME, TEST_PROVIDER_NAME); 104 assertNotNull(factory); 105 } catch (NoSuchAlgorithmException e) { 106 fail("unexpected exception: " + e); 107 } catch (NoSuchProviderException e) { 108 fail("unexpected exception: " + e); 109 } 110 111 String[][] combinations = { 112 { "UnknownKeyFactory", TEST_PROVIDER_NAME}, 113 { TEST_KEYFACTORY_NAME, "UnknownProvider"}, 114 { TEST_KEYFACTORY_NAME, existingProvider.getName() }, 115 { null, TEST_PROVIDER_NAME }, 116 { TEST_KEYFACTORY_NAME, null }, 117 { null, null} 118 }; 119 120 Class[] exceptions = { 121 NoSuchAlgorithmException.class, 122 NoSuchProviderException.class, 123 NoSuchAlgorithmException.class, 124 NullPointerException.class, 125 IllegalArgumentException.class, 126 IllegalArgumentException.class 127 }; 128 129 for (int i = 0; i < combinations.length; i++) { 130 String[] combination = combinations[i]; 131 String message = "getInstance(\"" + combination[0] + "\", \"" + combination[1] + "\")"; 132 exceptionThrown = false; 133 try { 134 KeyFactory.getInstance(combination[0], combination[1]); 135 } catch (Exception e) { 136 checkException(message, e, exceptions[i]); 137 } finally { 138 checkException(message, null, exceptions[i]); 139 } 140 } 141 } 142 143 @SuppressWarnings("unchecked") 144 @TestTargetNew( 145 level=TestLevel.COMPLETE, 146 method="getInstance", 147 args={String.class, Provider.class} 148 ) 149 public void testGetInstanceStringProvider() { 150 try { 151 KeyFactory factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME, provider); 152 assertNotNull(factory); 153 } catch (NoSuchAlgorithmException e) { 154 fail("unexpected exception: " + e); 155 } 156 157 String[] algorithms = { 158 "UnknownKeyFactory", 159 null, 160 TEST_KEYFACTORY_NAME, 161 TEST_KEYFACTORY_NAME 162 }; 163 164 Provider[] providers = { 165 provider, 166 provider, 167 existingProvider, 168 null 169 }; 170 171 Class[] exceptions = { 172 NoSuchAlgorithmException.class, 173 NullPointerException.class, 174 NoSuchAlgorithmException.class, 175 IllegalArgumentException.class 176 }; 177 178 for (int i = 0; i < algorithms.length; i++) { 179 String algorithm = algorithms[i]; 180 Provider provider = providers[i]; 181 String message = "getInstance(" + 182 (algorithm == null ? "null" : "\"" + algorithm + "\"") + 183 ", " + 184 (provider == null ? "null" : "provider"); 185 exceptionThrown = false; 186 try { 187 KeyFactory.getInstance(algorithm, provider); 188 } catch (Exception e) { 189 checkException(message, e, exceptions[i]); 190 } finally { 191 checkException(message, null, exceptions[i]); 192 } 193 194 } 195 } 196 197 @SuppressWarnings("unchecked") 198 @TestTargetNew( 199 level=TestLevel.COMPLETE, 200 method="generatePublic", 201 args={KeySpec.class} 202 ) 203 public void testGeneratePublic() { 204 KeyFactory factory = null; 205 try { 206 factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME); 207 } catch (NoSuchAlgorithmException e) { 208 fail("unexpected exception: " + e); 209 } 210 211 assertNotNull(factory); 212 213 try { 214 TestPublicKey key = new TestPublicKey(); 215 TestPublicKeySpec keySpec = new TestPublicKeySpec(key); 216 PublicKey publicKey = factory.generatePublic(keySpec); 217 assertNotNull(publicKey); 218 assertTrue(Arrays.equals(key.encoded, publicKey.getEncoded())); 219 } catch (InvalidKeySpecException e) { 220 fail("unexpected exception: " + e); 221 } 222 223 KeySpec[] keySpecs = { 224 new TestPrivateKeySpec(new TestPrivateKey()), 225 null, 226 new DSAPublicKeySpec(null, null, null, null) 227 }; 228 229 Class[] exceptions = { 230 InvalidKeySpecException.class, 231 NullPointerException.class, 232 InvalidKeySpecException.class 233 }; 234 235 for (int i = 0; i < keySpecs.length; i++) { 236 KeySpec keySpec = keySpecs[i]; 237 String message = "generatePublic(" + 238 (keySpec == null ? "null" : keySpec.toString()) + ")"; 239 240 try { 241 PublicKey generatePublic = factory.generatePublic(keySpec); 242 assertNotNull(generatePublic); 243 } catch (Exception e) { 244 checkException(message, e, exceptions[i]); 245 } finally { 246 checkException(message, null, exceptions[i]); 247 } 248 } 249 } 250 251 @SuppressWarnings("unchecked") 252 @TestTargetNew( 253 level=TestLevel.COMPLETE, 254 method="generatePrivate", 255 args={KeySpec.class} 256 ) 257 public void testGeneratePrivate() { 258 KeyFactory factory = null; 259 try { 260 factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME); 261 } catch (NoSuchAlgorithmException e) { 262 fail("unexpected exception: " + e); 263 } 264 265 assertNotNull(factory); 266 267 try { 268 TestPrivateKey key = new TestPrivateKey(); 269 TestPrivateKeySpec keySpec = new TestPrivateKeySpec(key); 270 PrivateKey privateKey = factory.generatePrivate(keySpec); 271 assertNotNull(privateKey); 272 assertTrue(Arrays.equals(key.getEncoded(), privateKey.getEncoded())); 273 } catch (InvalidKeySpecException e) { 274 fail("unexpected exception: " + e); 275 } 276 277 KeySpec[] keySpecs = { 278 new TestPublicKeySpec(new TestPublicKey()), 279 null, 280 new DSAPublicKeySpec(null, null, null, null) 281 }; 282 283 Class[] exceptions = { 284 InvalidKeySpecException.class, 285 NullPointerException.class, 286 InvalidKeySpecException.class 287 }; 288 289 for (int i = 0; i < keySpecs.length; i++) { 290 KeySpec keySpec = keySpecs[i]; 291 exceptionThrown = false; 292 String message = "generatePrivate(" + 293 (keySpec == null ? "null" : keySpec.toString()) + ")"; 294 try { 295 factory.generatePrivate(keySpec); 296 } catch (Exception e) { 297 checkException(message, e, exceptions[i]); 298 } finally { 299 checkException(message, null, exceptions[i]); 300 } 301 } 302 } 303 304 @SuppressWarnings("unchecked") 305 @TestTargetNew( 306 level=TestLevel.COMPLETE, 307 method="getKeySpec", 308 args={Key.class, Class.class} 309 ) 310 public void testGetKeySpec() { 311 KeyFactory factory = null; 312 try { 313 factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME); 314 } catch (NoSuchAlgorithmException e) { 315 fail("unexpected exception: " + e); 316 } 317 318 assertNotNull(factory); 319 320 { 321 Key[] keys = { 322 new TestPrivateKey(), 323 new TestPublicKey(), 324 new TestPrivateKey(new byte[] { 42, 41, 40 }), 325 new TestPublicKey(new byte[] { 40, 41, 42 }) 326 }; 327 328 Class[] keySpecs = { 329 TestPrivateKeySpec.class, 330 TestPublicKeySpec.class, 331 TestPrivateKeySpec.class, 332 TestPublicKeySpec.class, 333 }; 334 335 for (int i = 0; i < keys.length; i++) { 336 Key key = keys[i]; 337 Class keySpec = keySpecs[i]; 338 String message = "getKeySpec(" + key.toString() + ", " + keySpec.toString() + ")"; 339 try { 340 KeySpec spec = factory.getKeySpec(key, keySpec); 341 assertNotNull(spec); 342 assertTrue(spec.getClass() == keySpec); 343 } catch (InvalidKeySpecException e) { 344 fail("unexpected exception: " + e); 345 } 346 } 347 } 348 349 { 350 Key[] keys = { 351 new AnotherKey(), 352 null, 353 new TestPrivateKey(), 354 null, 355 }; 356 357 Class[] keySpecs = { 358 KeySpec.class, 359 TestPrivateKeySpec.class, 360 null, 361 null, 362 }; 363 364 Class[] exceptions = { 365 InvalidKeySpecException.class, 366 NullPointerException.class, 367 InvalidKeySpecException.class, 368 NullPointerException.class 369 }; 370 371 for (int i = 0; i < keys.length; i++) { 372 Key key = keys[i]; 373 Class keySpec = keySpecs[i]; 374 exceptionThrown = false; 375 String message = "getKeySpec(" + 376 (key == null ? "null" : key.toString()) + 377 ", " + 378 (keySpec == null ? "null" : keySpec.toString()) + ")"; 379 try { 380 factory.getKeySpec(key, keySpec); 381 } catch (Exception e) { 382 checkException(message, e, exceptions[i]); 383 } finally { 384 checkException(message, null, exceptions[i]); 385 } 386 387 } 388 } 389 } 390 391 @SuppressWarnings("unchecked") 392 @TestTargetNew( 393 level=TestLevel.COMPLETE, 394 method="translateKey", 395 args={Key.class} 396 ) 397 public void testTranslateKey() { 398 KeyFactory factory = null; 399 try { 400 factory = KeyFactory.getInstance(TEST_KEYFACTORY_NAME); 401 } catch (NoSuchAlgorithmException e) { 402 fail("unexpected exception: " + e); 403 } 404 405 assertNotNull(factory); 406 407 { 408 Key[] keys = { 409 new TestPrivateKey(), 410 new TestPublicKey() 411 }; 412 413 Class[] translated = { 414 TestPublicKey.class, 415 TestPrivateKey.class 416 }; 417 418 for (int i = 0; i < keys.length; i++) { 419 Key key = keys[i]; 420 Class translate = translated[i]; 421 try { 422 Key translateKey = factory.translateKey(key); 423 assertNotNull(translateKey); 424 assertEquals(translate, translateKey.getClass()); 425 } catch (InvalidKeyException e) { 426 fail("unexpected exception: " + e); 427 } 428 } 429 } 430 431 { 432 Key[] keys = { 433 new AnotherKey(), 434 null 435 }; 436 437 Class[] exceptions = { 438 InvalidKeyException.class, 439 NullPointerException.class 440 }; 441 442 for (int i = 0; i < keys.length; i++) { 443 Key key = keys[i]; 444 String message = "translateKey(" + 445 (key == null ? "null" : key.toString()) + ")"; 446 exceptionThrown = false; 447 try { 448 factory.translateKey(key); 449 } catch (Exception e) { 450 checkException(message, e, exceptions[i]); 451 } finally { 452 checkException(message, null, exceptions[i]); 453 } 454 } 455 } 456 } 457 458 private static final String TEST_PROVIDER_NAME = "TestKeyFactoryProvider"; 459 private static final String TEST_KEYFACTORY_NAME = "TestKeyFactory"; 460 461 static class TestKeyFactoryProvider extends Provider { 462 463 protected TestKeyFactoryProvider() { 464 super(TEST_PROVIDER_NAME, 1.1, "Test KeyFactory Provider"); 465 put("KeyFactory." + TEST_KEYFACTORY_NAME, TestKeyFactorySpi.class.getName()); 466 } 467 } 468 469 public static class TestKeyFactorySpi extends KeyFactorySpi { 470 471 @Override 472 protected PrivateKey engineGeneratePrivate(KeySpec keySpec) 473 throws InvalidKeySpecException { 474 if (TestPrivateKeySpec.class == keySpec.getClass()) { 475 return new TestPrivateKey(((TestPrivateKeySpec)keySpec).encoded); 476 } 477 478 throw new InvalidKeySpecException(); 479 } 480 481 @Override 482 protected PublicKey engineGeneratePublic(KeySpec keySpec) 483 throws InvalidKeySpecException { 484 if (TestPublicKeySpec.class == keySpec.getClass()) { 485 return new TestPublicKey(((TestPublicKeySpec)keySpec).encoded); 486 } 487 throw new InvalidKeySpecException(); 488 } 489 490 @Override 491 protected <T extends KeySpec> T engineGetKeySpec(Key key, 492 Class<T> keySpec) throws InvalidKeySpecException { 493 494 if (key == null) { 495 throw new NullPointerException(); 496 } 497 498 Constructor<T> constructor = null; 499 if (TestPrivateKeySpec.class == keySpec) { 500 try { 501 constructor = keySpec.getConstructor(TestPrivateKey.class); 502 } catch (SecurityException e) { 503 throw new InvalidKeySpecException(e); 504 } catch (NoSuchMethodException e) { 505 throw new InvalidKeySpecException(e); 506 } 507 } else if (TestPublicKeySpec.class == keySpec) { 508 try { 509 constructor = keySpec.getConstructor(TestPublicKey.class); 510 } catch (SecurityException e) { 511 throw new InvalidKeySpecException(e); 512 } catch (NoSuchMethodException e) { 513 throw new InvalidKeySpecException(e); 514 } 515 } 516 517 if (constructor == null) { 518 throw new InvalidKeySpecException(); 519 } 520 521 try { 522 return constructor.newInstance(key); 523 } catch (IllegalArgumentException e) { 524 throw new InvalidKeySpecException(e); 525 } catch (InstantiationException e) { 526 throw new InvalidKeySpecException(e); 527 } catch (IllegalAccessException e) { 528 throw new InvalidKeySpecException(e); 529 } catch (InvocationTargetException e) { 530 throw new InvalidKeySpecException(e); 531 } 532 } 533 534 @Override 535 protected Key engineTranslateKey(Key key) throws InvalidKeyException { 536 if (TestPrivateKey.class == key.getClass()) { 537 return new TestPublicKey(); 538 } else if (TestPublicKey.class == key.getClass()) { 539 return new TestPrivateKey(); 540 } 541 throw new InvalidKeyException(); 542 } 543 544 } 545 546 static class TestPrivateKeySpec implements KeySpec { 547 @SuppressWarnings("unused") 548 private final byte[] encoded; 549 550 public TestPrivateKeySpec(TestPrivateKey key) { 551 this.encoded = key.getEncoded(); 552 } 553 } 554 555 static class TestPublicKeySpec implements KeySpec { 556 @SuppressWarnings("unused") 557 private final byte[] encoded; 558 559 public TestPublicKeySpec(TestPublicKey key) { 560 this.encoded = key.getEncoded(); 561 } 562 } 563 564 static class TestPrivateKey implements PrivateKey { 565 566 private final byte[] encoded; 567 568 public TestPrivateKey() { 569 encoded = new byte[] {3, 4, 5}; 570 } 571 572 public TestPrivateKey(byte[] encoded) { 573 this.encoded = encoded; 574 } 575 576 public String getAlgorithm() { 577 return "TestPrivateKey"; 578 } 579 580 public byte[] getEncoded() { 581 return encoded; 582 } 583 584 public String getFormat() { 585 return "TestFormat"; 586 } 587 } 588 589 static class TestPublicKey implements PublicKey { 590 591 private final byte[] encoded; 592 593 public TestPublicKey() { 594 encoded = new byte[] {3, 4, 5}; 595 } 596 597 public TestPublicKey(byte[] encoded) { 598 this.encoded = encoded; 599 } 600 601 public String getAlgorithm() { 602 return "TestPublicKey"; 603 } 604 605 public byte[] getEncoded() { 606 return encoded; 607 } 608 609 public String getFormat() { 610 return "TestFormat"; 611 } 612 } 613 614 static class AnotherKey implements Key { 615 616 public String getAlgorithm() { 617 return "AnotherKey"; 618 } 619 620 public byte[] getEncoded() { 621 return null; 622 } 623 624 public String getFormat() { 625 return "AnotherFormat"; 626 } 627 628 } 629 630 private void checkException(String message, Exception thrown, Class<? extends Exception> expected) { 631 if (thrown == null) { 632 if (!exceptionThrown) { 633 fail(message + ", expected " + expected.getName()); 634 } 635 } else if (expected == thrown.getClass()) { 636 exceptionThrown = true; 637 // ok 638 } else { 639 exceptionThrown = true; 640 fail(message + ", unexpected exception: " + thrown + ", expected: " + expected.getName()); 641 } 642 } 643 644} 645