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.security.InvalidKeyException;
21import java.security.KeyFactory;
22import java.security.KeyPair;
23import java.security.KeyPairGenerator;
24import java.security.NoSuchAlgorithmException;
25import java.security.NoSuchProviderException;
26import java.security.PrivateKey;
27import java.security.Provider;
28import java.security.PublicKey;
29import java.security.SecureRandom;
30import java.security.Security;
31import java.security.spec.InvalidKeySpecException;
32import java.security.spec.KeySpec;
33import java.security.spec.PKCS8EncodedKeySpec;
34import java.security.spec.X509EncodedKeySpec;
35import java.util.Arrays;
36import java.util.Enumeration;
37import java.util.Vector;
38
39public class KeyFactory2Test extends junit.framework.TestCase {
40
41    private static final String KEYFACTORY_ID = "KeyFactory.";
42
43    private String[] keyfactAlgs = null;
44
45    private String providerName = null;
46
47    static class KeepAlive extends Thread {
48        int sleepTime, iterations;
49
50        public KeepAlive(int sleepTime, int iterations) {
51            this.sleepTime = sleepTime;
52            this.iterations = iterations;
53        }
54
55        public void run() {
56            synchronized (this) {
57                this.notify();
58            }
59            for (int i = 0; i < iterations; i++) {
60                try {
61                    Thread.sleep(sleepTime);
62                    System.out.print("[KA]");
63                } catch (InterruptedException e) {
64                    System.out.print("[I]");
65                    break;
66                }
67            }
68        }
69    }
70
71    private KeepAlive createKeepAlive(String alg) {
72        if (alg.equals("RSA")) {
73            // 32 minutes
74            KeepAlive keepalive = new KeepAlive(240000, 8);
75            synchronized (keepalive) {
76                keepalive.start();
77                try {
78                    keepalive.wait();
79                } catch (InterruptedException e) {
80                    // ignore
81                }
82            }
83            return keepalive;
84        }
85        return null;
86    }
87
88    /**
89     * @tests java.security.KeyFactory#generatePrivate(java.security.spec.KeySpec)
90     */
91    public void test_generatePrivateLjava_security_spec_KeySpec() {
92        // Test for method java.security.PrivateKey
93        // java.security.KeyFactory.generatePrivate(java.security.spec.KeySpec)
94        for (int i = 0; i < keyfactAlgs.length; i++) {
95            try {
96                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
97                        providerName);
98                KeyPairGenerator keyGen = KeyPairGenerator
99                        .getInstance(keyfactAlgs[i]);
100                SecureRandom random = new SecureRandom(); // We don't use
101                // getInstance
102                keyGen.initialize(1024, random);
103                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
104                KeyPair keys = keyGen.generateKeyPair();
105                if (keepalive != null) {
106                    keepalive.interrupt();
107                }
108
109                KeySpec privateKeySpec = fact.getKeySpec(keys.getPrivate(),
110                        getPrivateKeySpecClass(keyfactAlgs[i]));
111                PrivateKey privateKey = fact.generatePrivate(privateKeySpec);
112                boolean samePrivate = Arrays.equals(keys.getPrivate()
113                        .getEncoded(), privateKey.getEncoded());
114                assertTrue(
115                        "generatePrivate generated different key for algorithm "
116                                + keyfactAlgs[i], samePrivate);
117                fact.generatePrivate(new PKCS8EncodedKeySpec(keys.getPrivate()
118                        .getEncoded()));
119            } catch (InvalidKeySpecException e) {
120                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
121            } catch (NoSuchAlgorithmException e) {
122                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
123            } catch (NoSuchProviderException e) {
124                fail("getInstance did not find provider " + providerName);
125            }
126        }
127    }
128
129    /**
130     * @tests java.security.KeyFactory#generatePublic(java.security.spec.KeySpec)
131     */
132    public void test_generatePublicLjava_security_spec_KeySpec() {
133        // Test for method java.security.PublicKey
134        // java.security.KeyFactory.generatePublic(java.security.spec.KeySpec)
135        for (int i = 0; i < keyfactAlgs.length; i++) {
136            try {
137                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
138                        providerName);
139                KeyPairGenerator keyGen = KeyPairGenerator
140                        .getInstance(keyfactAlgs[i]);
141                // We don't use getInstance
142                SecureRandom random = new SecureRandom();
143                keyGen.initialize(1024, random);
144                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
145                KeyPair keys = keyGen.generateKeyPair();
146                if (keepalive != null) {
147                    keepalive.interrupt();
148                }
149                KeySpec publicKeySpec = fact.getKeySpec(keys.getPublic(),
150                        getPublicKeySpecClass(keyfactAlgs[i]));
151                PublicKey publicKey = fact.generatePublic(publicKeySpec);
152                boolean samePublic = Arrays.equals(keys.getPublic()
153                        .getEncoded(), publicKey.getEncoded());
154                assertTrue(
155                        "generatePublic generated different key for algorithm "
156                                + keyfactAlgs[i], samePublic);
157            } catch (NoSuchAlgorithmException e) {
158                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
159            } catch (NoSuchProviderException e) {
160                fail("getInstance did not find provider " + providerName);
161            } catch (InvalidKeySpecException e) {
162                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
163            }
164        }
165    }
166
167    /**
168     * @tests java.security.KeyFactory#getAlgorithm()
169     */
170    public void test_getAlgorithm() {
171        // Test for method java.lang.String
172        // java.security.KeyFactory.getAlgorithm()
173        for (int i = 0; i < keyfactAlgs.length; i++) {
174            try {
175                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
176                        providerName);
177                assertTrue("getAlgorithm ok for algorithm " + keyfactAlgs[i],
178                        fact.getAlgorithm().equals(keyfactAlgs[i]));
179            } catch (NoSuchAlgorithmException e) {
180                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
181            } catch (NoSuchProviderException e) {
182                fail("getInstance did not find provider " + providerName);
183            }
184        }// end for
185    }
186
187    /**
188     * @tests java.security.KeyFactory#getInstance(java.lang.String)
189     */
190    public void test_getInstanceLjava_lang_String() {
191        // Test for method java.security.KeyFactory
192        // java.security.KeyFactory.getInstance(java.lang.String)
193        for (int i = 0; i < keyfactAlgs.length; i++) {
194            try {
195                assertNotNull(KeyFactory.getInstance(keyfactAlgs[i]));
196            } catch (NoSuchAlgorithmException e) {
197                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
198            }
199        }// end for
200    }
201
202    /**
203     * @tests java.security.KeyFactory#getInstance(java.lang.String,
204     *java.lang.String)
205     */
206    public void test_getInstanceLjava_lang_StringLjava_lang_String() throws Exception {
207
208        // Test1: Test for method java.security.KeyFactory
209        // java.security.KeyFactory.getInstance(java.lang.String,
210        // java.lang.String)
211        try {
212            Provider[] providers = Security.getProviders("KeyFactory.DSA");
213            if (providers != null) {
214                for (int i = 0; i < providers.length; i++) {
215                    KeyFactory.getInstance("DSA", providers[i].getName());
216                }// end for
217            } else {
218                fail("No providers support KeyFactory.DSA");
219            }
220        } catch (NoSuchAlgorithmException e) {
221            fail("getInstance did not find algorithm");
222        } catch (NoSuchProviderException e) {
223            fail("getInstance did not find the provider");
224        }
225
226        // Test2: Test with null provider name
227        try {
228            KeyFactory.getInstance("DSA", (String) null);
229            fail("Expected IllegalArgumentException");
230        } catch (IllegalArgumentException e) {
231            // Expected
232        }
233    }
234
235    /**
236     * @tests java.security.KeyFactory#getKeySpec(java.security.Key,
237     *java.lang.Class)
238     */
239    public void test_getKeySpecLjava_security_KeyLjava_lang_Class() {
240        // Test for method java.security.spec.KeySpec
241        // java.security.KeyFactory.getKeySpec(java.security.Key,
242        // java.lang.Class)
243        for (int i = 0; i < keyfactAlgs.length; i++) {
244            try {
245                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
246                        providerName);
247                KeyPairGenerator keyGen = KeyPairGenerator
248                        .getInstance(keyfactAlgs[i]);
249
250                // We don't use getInstance
251                SecureRandom random = new SecureRandom();
252                keyGen.initialize(1024, random);
253                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
254                KeyPair keys = keyGen.generateKeyPair();
255                if (keepalive != null) {
256                    keepalive.interrupt();
257                }
258                KeySpec privateKeySpec = fact.getKeySpec(keys.getPrivate(),
259                        getPrivateKeySpecClass(keyfactAlgs[i]));
260                KeySpec publicKeySpec = fact.getKeySpec(keys.getPublic(),
261                        getPublicKeySpecClass(keyfactAlgs[i]));
262                PrivateKey privateKey = fact.generatePrivate(privateKeySpec);
263                PublicKey publicKey = fact.generatePublic(publicKeySpec);
264                boolean samePublic = Arrays.equals(keys.getPublic()
265                        .getEncoded(), publicKey.getEncoded());
266                boolean samePrivate = Arrays.equals(keys.getPrivate()
267                        .getEncoded(), privateKey.getEncoded());
268                assertTrue(
269                        "generatePrivate generated different key for algorithm "
270                                + keyfactAlgs[i], samePrivate);
271                assertTrue(
272                        "generatePublic generated different key for algorithm "
273                                + keyfactAlgs[i], samePublic);
274                KeySpec encodedSpec = fact.getKeySpec(keys.getPublic(),
275                        X509EncodedKeySpec.class);
276                assertTrue("improper key spec for encoded public key",
277                        encodedSpec.getClass().equals(X509EncodedKeySpec.class));
278                encodedSpec = fact.getKeySpec(keys.getPrivate(),
279                        PKCS8EncodedKeySpec.class);
280                assertTrue("improper key spec for encoded private key",
281                        encodedSpec.getClass()
282                                .equals(PKCS8EncodedKeySpec.class));
283            } catch (NoSuchAlgorithmException e) {
284                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
285            } catch (NoSuchProviderException e) {
286                fail("getInstance did not find provider " + providerName);
287            } catch (InvalidKeySpecException e) {
288                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
289            }
290        }
291    }
292
293    /**
294     * @tests java.security.KeyFactory#getProvider()
295     */
296    public void test_getProvider() {
297        // Test for method java.security.Provider
298        // java.security.KeyFactory.getProvider()
299        for (int i = 0; i < keyfactAlgs.length; i++) {
300            try {
301                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i]);
302                Provider p = fact.getProvider();
303                assertNotNull("provider is null for algorithm "
304                        + keyfactAlgs[i], p);
305            } catch (NoSuchAlgorithmException e) {
306                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
307            }
308        }// end for
309    }
310
311    /**
312     * @tests java.security.KeyFactory#translateKey(java.security.Key)
313     */
314    public void test_translateKeyLjava_security_Key() {
315        // Test for method java.security.Key
316        // java.security.KeyFactory.translateKey(java.security.Key)
317        for (int i = 0; i < keyfactAlgs.length; i++) {
318            try {
319                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
320                        providerName);
321                KeyPairGenerator keyGen = KeyPairGenerator
322                        .getInstance(keyfactAlgs[i]);
323
324                // We don't use getInstance
325                SecureRandom random = new SecureRandom();
326                keyGen.initialize(1024, random);
327                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
328                KeyPair keys = keyGen.generateKeyPair();
329                if (keepalive != null) {
330                    keepalive.interrupt();
331                }
332                fact.translateKey(keys.getPrivate());
333            } catch (NoSuchAlgorithmException e) {
334                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
335            } catch (NoSuchProviderException e) {
336                fail("getInstance did not find provider " + providerName);
337            } catch (InvalidKeyException e) {
338                fail("generatePublic did not generate right spec for algorithm "
339                        + keyfactAlgs[i]);
340            }
341        }
342    }
343
344    protected void setUp() {
345        if (keyfactAlgs == null) {
346            Provider[] providers = Security.getProviders();
347            // Arbitrarily use the first provider that supports
348            // KeyFactory algorithms
349            for (Provider provider : providers) {
350                providerName = provider.getName();
351                keyfactAlgs = getKeyFactoryAlgorithms(providerName);
352                if (keyfactAlgs.length != 0) {
353                    break;
354                }
355            }
356        }
357    }
358
359    /*
360      * Returns the key algorithms that the given provider supports.
361      */
362    private String[] getKeyFactoryAlgorithms(String providerName) {
363        Vector algs = new Vector();
364
365        Provider provider = Security.getProvider(providerName);
366        if (provider == null)
367            return new String[0];
368        Enumeration e = provider.keys();
369        while (e.hasMoreElements()) {
370            String algorithm = (String) e.nextElement();
371            if (algorithm.startsWith(KEYFACTORY_ID) && !algorithm.contains(" ")) {
372                algs.addElement(algorithm.substring(KEYFACTORY_ID.length()));
373            }
374        }
375
376        return (String[]) algs.toArray(new String[algs.size()]);
377    }
378
379    /**
380     * Returns the public key spec class for a given algorithm, or null if it is
381     * not known.
382     */
383    private Class getPrivateKeySpecClass(String algName) {
384        if (algName.equals("RSA")) {
385            return java.security.spec.RSAPrivateCrtKeySpec.class;
386        }
387        if (algName.equals("DSA")) {
388            return java.security.spec.DSAPrivateKeySpec.class;
389        }
390        return null;
391    }
392
393    /**
394     * Returns the private key spec class for a given algorithm, or null if it
395     * is not known.
396     */
397    private Class getPublicKeySpecClass(String algName) {
398        if (algName.equals("RSA")) {
399            return java.security.spec.RSAPublicKeySpec.class;
400        }
401        if (algName.equals("DSA")) {
402            return java.security.spec.DSAPublicKeySpec.class;
403        }
404        return null;
405    }
406}
407