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