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
18/**
19* @author Vera Y. Petrashkova
20* @version $Revision$
21*/
22
23package org.apache.harmony.crypto.tests.javax.crypto;
24
25import java.math.BigInteger;
26import java.security.InvalidAlgorithmParameterException;
27import java.security.InvalidParameterException;
28import java.security.NoSuchAlgorithmException;
29import java.security.NoSuchProviderException;
30import java.security.Provider;
31import java.security.SecureRandom;
32import java.security.spec.AlgorithmParameterSpec;
33import java.security.spec.DSAParameterSpec;
34import java.security.spec.RSAKeyGenParameterSpec;
35
36import javax.crypto.Cipher;
37import javax.crypto.KeyGenerator;
38import javax.crypto.KeyGeneratorSpi;
39import javax.crypto.SecretKey;
40import javax.crypto.spec.IvParameterSpec;
41
42import org.apache.harmony.crypto.tests.support.MyKeyGeneratorSpi;
43import org.apache.harmony.security.tests.support.SpiEngUtils;
44
45import junit.framework.TestCase;
46
47
48/**
49 * Tests for KeyGenerator constructor and methods
50 *
51 */
52public class KeyGeneratorTest extends TestCase {
53
54    public static final String srvKeyGenerator = "KeyGenerator";
55
56    public static final String validAlgorithmsKeyGenerator [] =
57        {"DESede", "DES", "AES", "HmacMD5"};
58
59    private static final int [] validKeySizes = { 168, 56, 256, 56};
60
61    private static int defaultKeySize = -1;
62
63    private static String defaultAlgorithm = null;
64
65    private static String defaultProviderName = null;
66
67    private static Provider defaultProvider = null;
68
69    private static boolean DEFSupported = false;
70
71    private static final String NotSupportMsg = "There is no suitable provider for KeyGenerator";
72
73    private static final String[] invalidValues = SpiEngUtils.invalidValues;
74
75    private static String[] validValues = new String[3];
76
77    static {
78        for (int i = 0; i < validAlgorithmsKeyGenerator.length; i++) {
79            defaultProvider = SpiEngUtils.isSupport(validAlgorithmsKeyGenerator[i],
80                srvKeyGenerator);
81            DEFSupported = (defaultProvider != null);
82            if (DEFSupported) {
83                defaultAlgorithm = validAlgorithmsKeyGenerator[i];
84                defaultKeySize = validKeySizes[i];
85                defaultProviderName = defaultProvider.getName();
86                validValues[0] = defaultAlgorithm;
87                validValues[1] = defaultAlgorithm.toUpperCase();
88                validValues[2] = defaultAlgorithm.toLowerCase();
89                break;
90            }
91        }
92    }
93
94    private KeyGenerator[] createKGs() throws Exception {
95        if (!DEFSupported) {
96            fail(NotSupportMsg);
97        }
98
99        KeyGenerator [] kg = new KeyGenerator[3];
100        kg[0] = KeyGenerator.getInstance(defaultAlgorithm);
101        kg[1] = KeyGenerator.getInstance(defaultAlgorithm, defaultProvider);
102        kg[2] = KeyGenerator.getInstance(defaultAlgorithm, defaultProviderName);
103        return kg;
104    }
105
106
107    /**
108     * Test for <code>KeyGenerator</code> constructor Assertion: returns
109     * KeyGenerator object
110     */
111    public void testKeyGenerator() throws NoSuchAlgorithmException,
112            InvalidAlgorithmParameterException {
113        if (!DEFSupported) {
114            fail(NotSupportMsg);
115            return;
116        }
117        KeyGeneratorSpi spi = new MyKeyGeneratorSpi();
118        KeyGenerator keyG = new myKeyGenerator(spi, defaultProvider,
119                defaultAlgorithm);
120        assertEquals("Incorrect algorithm", keyG.getAlgorithm(),
121                defaultAlgorithm);
122        assertEquals("Incorrect provider", keyG.getProvider(), defaultProvider);
123        AlgorithmParameterSpec params = null;
124        int keysize = 0;
125        try {
126            keyG.init(params, null);
127            fail("InvalidAlgorithmParameterException must be thrown");
128        } catch (InvalidAlgorithmParameterException e) {
129        }
130        try {
131            keyG.init(keysize, null);
132            fail("IllegalArgumentException must be thrown");
133        } catch (IllegalArgumentException e) {
134        }
135        keyG = new myKeyGenerator(null, null, null);
136        assertNull("Algorithm must be null", keyG.getAlgorithm());
137        assertNull("Provider must be null", keyG.getProvider());
138
139        try {
140            keyG.init(params, null);
141            fail("NullPointerException must be thrown");
142        } catch (NullPointerException e) {
143        }
144        try {
145            keyG.init(keysize, null);
146            fail("NullPointerException or InvalidParameterException must be thrown");
147        } catch (InvalidParameterException e) {
148        } catch (NullPointerException e) {
149        }
150    }
151
152    /*
153     * Test for <code> getInstance(String algorithm) </code> method Assertions:
154     * throws NullPointerException when algorithm is null throws
155     * NoSuchAlgorithmException when algorithm isnot available
156     */
157    public void testGetInstanceString01() throws NoSuchAlgorithmException {
158        try {
159            KeyGenerator.getInstance(null);
160            fail("NullPointerException or NoSuchAlgorithmException should be thrown if algorithm is null");
161        } catch (NullPointerException e) {
162        } catch (NoSuchAlgorithmException e) {
163        }
164        for (int i = 0; i < invalidValues.length; i++) {
165            try {
166                KeyGenerator.getInstance(invalidValues[i]);
167                fail("NoSuchAlgorithmException should be thrown");
168            } catch (NoSuchAlgorithmException e) {
169            }
170        }
171    }
172
173    /*
174     * Test for <code> getInstance(String algorithm) </code> method
175     * Assertions: returns KeyGenerator object
176     */
177    public void testGetInstanceString02() throws NoSuchAlgorithmException {
178        if (!DEFSupported) {
179            fail(NotSupportMsg);
180            return;
181        }
182        KeyGenerator keyG;
183        for (int i = 0; i < validValues.length; i++) {
184            keyG = KeyGenerator.getInstance(validValues[i]);
185            assertEquals("Incorrect algorithm", keyG.getAlgorithm(), validValues[i]);
186        }
187    }
188
189    /*
190     * Test for <code> getInstance(String algorithm, String provider)</code> method
191     * Assertions:
192     * throws NullPointerException when algorithm is null
193     * throws NoSuchAlgorithmException when algorithm isnot available
194     */
195    public void testGetInstanceStringString01() throws
196            NoSuchAlgorithmException, IllegalArgumentException,
197            NoSuchProviderException {
198        if (!DEFSupported) {
199            fail(NotSupportMsg);
200            return;
201        }
202        try {
203            KeyGenerator.getInstance(null, defaultProviderName);
204            fail("NullPointerException or NoSuchAlgorithmException should be thrown if algorithm is null");
205        } catch (NullPointerException e) {
206        } catch (NoSuchAlgorithmException e) {
207        }
208        for (int i = 0; i < invalidValues.length; i++) {
209            try {
210                KeyGenerator.getInstance(invalidValues[i], defaultProviderName);
211                fail("NoSuchAlgorithmException must be thrown");
212            } catch (NoSuchAlgorithmException e) {
213            }
214        }
215    }
216
217    /*
218     * Test for <code> getInstance(String algorithm, String provider)</code> method
219     * Assertions:
220     * throws IllegalArgumentException when provider is null or empty
221     * throws NoSuchProviderException when provider has not be configured
222     */
223    public void testGetInstanceStringString02() throws IllegalArgumentException,
224            NoSuchAlgorithmException, NoSuchProviderException {
225        if (!DEFSupported) {
226            fail(NotSupportMsg);
227            return;
228        }
229        String provider = null;
230        for (int i = 0; i < validValues.length; i++) {
231            try {
232                KeyGenerator.getInstance(validValues[i], provider);
233                fail("IllegalArgumentException must be thrown when provider is null");
234            } catch (IllegalArgumentException e) {
235            }
236            try {
237                KeyGenerator.getInstance(validValues[i], "");
238                fail("IllegalArgumentException must be thrown when provider is empty");
239            } catch (IllegalArgumentException e) {
240            }
241            for (int j = 1; j < invalidValues.length; j++) {
242                try {
243                    KeyGenerator.getInstance(validValues[i], invalidValues[j]);
244                    fail("NoSuchProviderException must be thrown (algorithm: "
245                            .concat(validValues[i]).concat(" provider: ")
246                            .concat(invalidValues[j]).concat(")"));
247                } catch (NoSuchProviderException e) {
248                }
249            }
250        }
251    }
252
253    /*
254     * Test for <code> getInstance(String algorithm, String provider)</code> method
255     * Assertions: returns KeyGenerator object
256     */
257    public void testGetInstanceStringString03() throws IllegalArgumentException,
258            NoSuchAlgorithmException, NoSuchProviderException {
259        if (!DEFSupported) {
260            fail(NotSupportMsg);
261            return;
262        }
263        KeyGenerator keyG;
264        for (int i = 0; i < validValues.length; i++) {
265            keyG = KeyGenerator.getInstance(validValues[i], defaultProviderName);
266            assertEquals("Incorrect algorithm", keyG.getAlgorithm(), validValues[i]);
267            assertEquals("Incorrect provider", keyG.getProvider().getName(), defaultProviderName);
268        }
269    }
270
271    /*
272     * Test for <code> getInstance(String algorithm, Provider provider)</code> method
273     * Assertions:
274     * throws NullPointerException when algorithm is null
275     * throws NoSuchAlgorithmException when algorithm isnot available
276     */
277    public void testGetInstanceStringProvider01() throws NoSuchAlgorithmException,
278            IllegalArgumentException {
279        if (!DEFSupported) {
280            fail(NotSupportMsg);
281            return;
282        }
283        try {
284            KeyGenerator.getInstance(null, defaultProvider);
285            fail("NullPointerException or NoSuchAlgorithmException should be thrown if algorithm is null");
286        } catch (NullPointerException e) {
287        } catch (NoSuchAlgorithmException e) {
288        }
289        for (int i = 0; i < invalidValues.length; i++) {
290            try {
291                KeyGenerator.getInstance(invalidValues[i], defaultProvider);
292                fail("NoSuchAlgorithmException must be thrown");
293            } catch (NoSuchAlgorithmException e) {
294            }
295        }
296    }
297    /*
298     * Test for <code> getInstance(String algorithm, Provider provider)</code> method
299     * Assertions:
300     * throws IllegalArgumentException when provider is null
301     */
302    public void testGetInstanceStringProvider02() throws NoSuchAlgorithmException,
303            IllegalArgumentException {
304        if (!DEFSupported) {
305            fail(NotSupportMsg);
306            return;
307        }
308        Provider provider = null;
309        for (int i = 0; i < invalidValues.length; i++) {
310            try {
311                KeyGenerator.getInstance(invalidValues[i], provider);
312                fail("IllegalArgumentException must be thrown");
313            } catch (IllegalArgumentException e) {
314            }
315        }
316    }
317
318    /*
319     * Test for <code> getInstance(String algorithm, Provider provider)</code> method
320     * Assertions: returns KeyGenerator object
321     */
322    public void testGetInstanceStringProvider03() throws IllegalArgumentException,
323            NoSuchAlgorithmException {
324        if (!DEFSupported) {
325            fail(NotSupportMsg);
326            return;
327        }
328        KeyGenerator keyA;
329        for (int i = 0; i < validValues.length; i++) {
330            keyA = KeyGenerator.getInstance(validValues[i], defaultProvider);
331            assertEquals("Incorrect algorithm", keyA.getAlgorithm(), validValues[i]);
332            assertEquals("Incorrect provider", keyA.getProvider(), defaultProvider);
333        }
334    }
335
336    /*
337     * Test for <code>init(int keysize)</code> and
338     * <code>init(int keysize, SecureRandom random)</code> methods
339     * Assertion: throws InvalidParameterException if keysize is wrong
340     *
341     */
342    public void testInitKey() throws Exception {
343        byte flag = 0xF;
344        if (!DEFSupported) {
345            fail(NotSupportMsg);
346            return;
347        }
348        if (defaultAlgorithm
349                .equals(validAlgorithmsKeyGenerator[validAlgorithmsKeyGenerator.length - 1])) {
350            return;
351        }
352        int[] size = { Integer.MIN_VALUE, -1, 0, 112, 168, Integer.MAX_VALUE };
353        KeyGenerator[] kgs = createKGs();
354        SecureRandom random = new SecureRandom();
355
356        for (int i = 0; i < kgs.length; i++) {
357            // This both serves to ensure that we're testing the default provider and forces
358            // the implementation to lock in the provider, even if later calls fail
359            assertEquals(defaultProvider, kgs[i].getProvider());
360            for (int j = 0; j < size.length; j++) {
361                try {
362                    kgs[i].init(size[j]);
363                    flag &= 0xE;
364                } catch (InvalidParameterException ignore) {
365                    flag &= 0xD;
366                }
367
368                try {
369                    kgs[i].init(size[j], random);
370                    flag &= 0xB;
371             } catch (InvalidParameterException ignore) {
372                 flag &= 0x7;
373                }
374            }
375        }
376        assertTrue(flag == 0);
377    }
378
379    /*
380     * Test for <code>init(AlgorithmParameterSpec params)</code> and
381     * <code>init(AlgorithmParameterSpec params, SecureRandom random)</code> methods
382     * Assertion: throws InvalidAlgorithmParameterException when params is null
383     */
384    public void testInitParams() throws Exception {
385        if (!DEFSupported) {
386            fail(NotSupportMsg);
387            return;
388        }
389        KeyGenerator [] kgs = createKGs();
390        AlgorithmParameterSpec aps = null;
391
392        for (int i = 0; i < kgs.length; i++) {
393            try {
394                kgs[i].init(aps);
395                fail("InvalidAlgorithmParameterException must be thrown");
396            } catch (InvalidAlgorithmParameterException e) {
397            }
398            try {
399                kgs[i].init(aps, new SecureRandom());
400                fail("InvalidAlgorithmParameterException must be thrown");
401            } catch (InvalidAlgorithmParameterException e) {
402            }
403        }
404    }
405
406    /*
407     * Test for <code>generateKey()</code> and
408     * <code>init(SecureRandom random)</code> methods
409     * <code>init(int keysize, SecureRandom random)</code> methods
410     * <code>init(int keysize)</code> methods
411     * <code>init(AlgorithmParameterSpec params, SecureRandom random)</code> methods
412     * <code>init(AlgorithmParameterSpec params)</code> methods
413     * Assertions:
414     * initializes KeyGenerator;
415     * returns SecretKey object
416     *
417     */
418    public void testGenerateKey() throws Exception {
419        if (!DEFSupported) {
420            fail(NotSupportMsg);
421            return;
422        }
423        SecretKey sKey;
424        String dAl = defaultAlgorithm.toUpperCase();
425
426        KeyGenerator[] kgs = createKGs();
427
428        for (int i = 0; i < kgs.length; i++) {
429            sKey = kgs[i].generateKey();
430            assertEquals("Incorrect algorithm", sKey.getAlgorithm()
431                    .toUpperCase(), dAl);
432            kgs[i].init(new SecureRandom());
433            sKey = kgs[i].generateKey();
434            assertEquals("Incorrect algorithm", sKey.getAlgorithm()
435                    .toUpperCase(), dAl);
436            kgs[i].init(defaultKeySize);
437            sKey = kgs[i].generateKey();
438            assertEquals("Incorrect algorithm", sKey.getAlgorithm()
439                    .toUpperCase(), dAl);
440            kgs[i].init(defaultKeySize, new SecureRandom());
441            sKey = kgs[i].generateKey();
442            assertEquals("Incorrect algorithm", sKey.getAlgorithm()
443                    .toUpperCase(), dAl);
444        }
445    }
446
447    public void test_getAlgorithm() throws NoSuchAlgorithmException {
448        KeyGenerator kg = null;
449
450        for (int i = 0; i < validAlgorithmsKeyGenerator.length; i++) {
451            kg = KeyGenerator.getInstance(validAlgorithmsKeyGenerator[i]);
452            assertEquals(validAlgorithmsKeyGenerator[i], kg.getAlgorithm());
453        }
454
455        kg = new myKeyGenerator(null, null, null);
456        assertNull(kg.getAlgorithm());
457    }
458
459    public void test_getProvider () throws NoSuchAlgorithmException {
460        KeyGenerator kg = null;
461
462        for (int i = 0; i < validAlgorithmsKeyGenerator.length; i++) {
463            kg = KeyGenerator.getInstance(validAlgorithmsKeyGenerator[i]);
464            assertNotNull(kg.getProvider());
465        }
466
467        kg = new myKeyGenerator(null, null, null);
468        assertNull(kg.getProvider());
469    }
470
471    public void test_initILjava_security_SecureRandom() throws NoSuchAlgorithmException {
472        SecureRandom random = null;
473        KeyGenerator kg = null;
474
475        for (int i = 0; i < validAlgorithmsKeyGenerator.length; i++) {
476            kg = KeyGenerator.getInstance(validAlgorithmsKeyGenerator[i]);
477            random = new SecureRandom();
478            kg.init(validKeySizes[i], random);
479            assertNotNull(kg.getProvider());
480        }
481
482        kg = KeyGenerator.getInstance(validAlgorithmsKeyGenerator[0]);
483
484        try {
485            kg.init(5, random);
486            fail("InvalidParameterException expected");
487        } catch (InvalidParameterException e) {
488            //expected
489        }
490    }
491
492    public void test_Ljava_security_SecureRandom() throws NoSuchAlgorithmException {
493        SecureRandom random = null;
494        KeyGenerator kg = null;
495
496        for (int i = 0; i < validAlgorithmsKeyGenerator.length; i++) {
497            kg = KeyGenerator.getInstance(validAlgorithmsKeyGenerator[i]);
498            random = new SecureRandom();
499            kg.init(random);
500            assertNotNull(kg.getProvider());
501        }
502    }
503
504    public void test_initLjava_security_spec_AlgorithmParameterSpec ()
505            throws Exception {
506        KeyGenerator kg = null;
507
508        IvParameterSpec aps = null;
509        SecureRandom sr = new SecureRandom();
510
511        byte[] iv = null;
512        iv = new byte[8];
513        sr.nextBytes(iv);
514        aps = new IvParameterSpec(iv);
515
516        for (int i = 0; i < validAlgorithmsKeyGenerator.length; i++) {
517            kg = KeyGenerator.getInstance(validAlgorithmsKeyGenerator[i]);
518            try {
519                kg.init(aps);
520            } catch (InvalidAlgorithmParameterException e) {
521            }
522            assertNotNull(kg.getProvider());
523        }
524    }
525}
526
527/**
528 * Additional class for KeyGenerator constructor verification
529 */
530class myKeyGenerator extends KeyGenerator {
531
532    public myKeyGenerator(KeyGeneratorSpi keyAgreeSpi, Provider provider,
533            String algorithm) {
534        super(keyAgreeSpi, provider, algorithm);
535    }
536}
537