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