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