1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.java.security;
18
19import java.math.BigInteger;
20import java.security.Key;
21import java.security.KeyFactory;
22import java.security.KeyPair;
23import java.security.KeyPairGenerator;
24import java.security.PrivateKey;
25import java.security.Provider;
26import java.security.Provider.Service;
27import java.security.PublicKey;
28import java.security.SecureRandom;
29import java.security.Security;
30import java.security.interfaces.DSAParams;
31import java.security.interfaces.DSAPrivateKey;
32import java.security.interfaces.DSAPublicKey;
33import java.security.spec.DSAParameterSpec;
34import java.security.spec.PKCS8EncodedKeySpec;
35import java.security.spec.X509EncodedKeySpec;
36import java.util.ArrayList;
37import java.util.Arrays;
38import java.util.HashMap;
39import java.util.List;
40import java.util.Map;
41import java.util.Set;
42
43import junit.framework.TestCase;
44
45public class KeyPairGeneratorTest extends TestCase {
46
47    public void test_getInstance() throws Exception {
48        Provider[] providers = Security.getProviders();
49        for (Provider provider : providers) {
50            Set<Provider.Service> services = provider.getServices();
51            for (Provider.Service service : services) {
52                String type = service.getType();
53                if (!type.equals("KeyPairGenerator")) {
54                    continue;
55                }
56                String algorithm = service.getAlgorithm();
57                try {
58                    // KeyPairGenerator.getInstance(String)
59                    KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(algorithm);
60                    assertEquals(algorithm, kpg1.getAlgorithm());
61                    test_KeyPairGenerator(kpg1);
62
63                    // KeyPairGenerator.getInstance(String, Provider)
64                    KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(algorithm, provider);
65                    assertEquals(algorithm, kpg2.getAlgorithm());
66                    assertEquals(provider, kpg2.getProvider());
67                    test_KeyPairGenerator(kpg2);
68
69                    // KeyPairGenerator.getInstance(String, String)
70                    KeyPairGenerator kpg3 = KeyPairGenerator.getInstance(algorithm,
71                                                                        provider.getName());
72                    assertEquals(algorithm, kpg3.getAlgorithm());
73                    assertEquals(provider, kpg3.getProvider());
74                    test_KeyPairGenerator(kpg3);
75                } catch (Exception e) {
76                    throw new Exception("Problem testing KeyPairGenerator." + algorithm, e);
77                }
78            }
79        }
80    }
81
82    private static final Map<String, List<Integer>> KEY_SIZES
83            = new HashMap<String, List<Integer>>();
84    private static void putKeySize(String algorithm, int keySize) {
85        algorithm = algorithm.toUpperCase();
86        List<Integer> keySizes = KEY_SIZES.get(algorithm);
87        if (keySizes == null) {
88            keySizes = new ArrayList<Integer>();
89            KEY_SIZES.put(algorithm, keySizes);
90        }
91        keySizes.add(keySize);
92    }
93    private static List<Integer> getKeySizes(String algorithm) throws Exception {
94        algorithm = algorithm.toUpperCase();
95        List<Integer> keySizes = KEY_SIZES.get(algorithm);
96        if (keySizes == null) {
97            throw new Exception("Unknown key sizes for KeyPairGenerator." + algorithm);
98        }
99        return keySizes;
100    }
101    static {
102        putKeySize("DSA", 512);
103        putKeySize("DSA", 512+64);
104        putKeySize("DSA", 1024);
105        putKeySize("RSA", 512);
106        putKeySize("DH", 512);
107        putKeySize("DH", 512+64);
108        putKeySize("DH", 1024);
109        putKeySize("DiffieHellman", 512);
110        putKeySize("DiffieHellman", 512+64);
111        putKeySize("DiffieHellman", 1024);
112        putKeySize("EC", 256);
113    }
114
115    private void test_KeyPairGenerator(KeyPairGenerator kpg) throws Exception {
116        // without a call to initialize
117        test_KeyPair(kpg, kpg.genKeyPair());
118        test_KeyPair(kpg, kpg.generateKeyPair());
119
120        String algorithm = kpg.getAlgorithm();
121        List<Integer> keySizes = getKeySizes(algorithm);
122        for (int keySize : keySizes) {
123            kpg.initialize(keySize);
124            test_KeyPair(kpg, kpg.genKeyPair());
125            test_KeyPair(kpg, kpg.generateKeyPair());
126
127            kpg.initialize(keySize, (SecureRandom) null);
128            test_KeyPair(kpg, kpg.genKeyPair());
129            test_KeyPair(kpg, kpg.generateKeyPair());
130
131            kpg.initialize(keySize, new SecureRandom());
132            test_KeyPair(kpg, kpg.genKeyPair());
133            test_KeyPair(kpg, kpg.generateKeyPair());
134        }
135    }
136
137    private void test_KeyPair(KeyPairGenerator kpg, KeyPair kp) throws Exception {
138        assertNotNull(kp);
139        test_Key(kpg, kp.getPrivate());
140        test_Key(kpg, kp.getPublic());
141    }
142
143    private void test_Key(KeyPairGenerator kpg, Key k) throws Exception {
144        String expectedAlgorithm = kpg.getAlgorithm().toUpperCase();
145        if (StandardNames.IS_RI && expectedAlgorithm.equals("DIFFIEHELLMAN")) {
146            expectedAlgorithm = "DH";
147        }
148        assertEquals(expectedAlgorithm, k.getAlgorithm().toUpperCase());
149        assertNotNull(k.getEncoded());
150        assertNotNull(k.getFormat());
151
152        test_KeyWithAllKeyFactories(k);
153    }
154
155    private void test_KeyWithAllKeyFactories(Key k) throws Exception {
156        byte[] encoded = k.getEncoded();
157
158        String keyAlgo = k.getAlgorithm();
159
160        Provider[] providers = Security.getProviders();
161        for (Provider p : providers) {
162            Set<Provider.Service> services = p.getServices();
163            for (Provider.Service service : services) {
164                if (!"KeyFactory".equals(service.getType())) {
165                    continue;
166                }
167                if (!service.getAlgorithm().equals(keyAlgo)) {
168                    continue;
169                }
170
171                if ("PKCS#8".equals(k.getFormat())) {
172                    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded);
173                    KeyFactory kf = KeyFactory.getInstance(k.getAlgorithm(), p);
174                    PrivateKey privKey = kf.generatePrivate(spec);
175                    assertNotNull(privKey);
176                    assertTrue(Arrays.equals(privKey.getEncoded(), encoded));
177                } else if ("X.509".equals(k.getFormat())) {
178                    X509EncodedKeySpec spec = new X509EncodedKeySpec(encoded);
179                    KeyFactory kf = KeyFactory.getInstance(k.getAlgorithm(), p);
180                    PublicKey pubKey = kf.generatePublic(spec);
181                    assertNotNull(pubKey);
182                    assertTrue(Arrays.equals(encoded, pubKey.getEncoded()));
183                }
184            }
185        }
186    }
187
188    private static final BigInteger DSA_P = new BigInteger(new byte[] {
189        (byte) 0x00, (byte) 0x9e, (byte) 0x61, (byte) 0xc2, (byte) 0x89, (byte) 0xef, (byte) 0x77, (byte) 0xa9,
190        (byte) 0x4e, (byte) 0x13, (byte) 0x67, (byte) 0x64, (byte) 0x1f, (byte) 0x09, (byte) 0x01, (byte) 0xfe,
191        (byte) 0x24, (byte) 0x13, (byte) 0x53, (byte) 0xe0, (byte) 0xb7, (byte) 0x90, (byte) 0xa8, (byte) 0x4e,
192        (byte) 0x76, (byte) 0xfe, (byte) 0x89, (byte) 0x82, (byte) 0x7f, (byte) 0x7a, (byte) 0xc5, (byte) 0x3c,
193        (byte) 0x4e, (byte) 0x0c, (byte) 0x20, (byte) 0x55, (byte) 0x30, (byte) 0x95, (byte) 0x42, (byte) 0x85,
194        (byte) 0xe1, (byte) 0x40, (byte) 0x7d, (byte) 0x27, (byte) 0x8f, (byte) 0x07, (byte) 0x0d, (byte) 0xe8,
195        (byte) 0xdc, (byte) 0x99, (byte) 0xef, (byte) 0xb3, (byte) 0x07, (byte) 0x94, (byte) 0x34, (byte) 0xd6,
196        (byte) 0x7c, (byte) 0xff, (byte) 0x9c, (byte) 0xbe, (byte) 0x69, (byte) 0xd3, (byte) 0xeb, (byte) 0x44,
197        (byte) 0x37, (byte) 0x50, (byte) 0xef, (byte) 0x49, (byte) 0xf8, (byte) 0xe2, (byte) 0x5b, (byte) 0xd8,
198        (byte) 0xd1, (byte) 0x10, (byte) 0x84, (byte) 0x97, (byte) 0xea, (byte) 0xe3, (byte) 0xa5, (byte) 0x1c,
199        (byte) 0xc0, (byte) 0x4e, (byte) 0x69, (byte) 0xca, (byte) 0x70, (byte) 0x3d, (byte) 0x78, (byte) 0xb9,
200        (byte) 0x16, (byte) 0xe5, (byte) 0xfe, (byte) 0x61, (byte) 0x5d, (byte) 0x8a, (byte) 0x5a, (byte) 0xb3,
201        (byte) 0x2c, (byte) 0x61, (byte) 0xb6, (byte) 0x01, (byte) 0x3b, (byte) 0xd0, (byte) 0x01, (byte) 0x7c,
202        (byte) 0x32, (byte) 0x8d, (byte) 0xe1, (byte) 0xf3, (byte) 0x69, (byte) 0x0e, (byte) 0x8b, (byte) 0x58,
203        (byte) 0xc6, (byte) 0xcf, (byte) 0x00, (byte) 0x94, (byte) 0xf8, (byte) 0x49, (byte) 0x2a, (byte) 0x4b,
204        (byte) 0xea, (byte) 0xda, (byte) 0x00, (byte) 0xff, (byte) 0x4b, (byte) 0xd0, (byte) 0xbe, (byte) 0x40,
205        (byte) 0x23,
206    });
207
208    private static final BigInteger DSA_Q = new BigInteger(new byte[] {
209        (byte) 0x00, (byte) 0xbf, (byte) 0xee, (byte) 0xaa, (byte) 0x0f, (byte) 0x12, (byte) 0x34, (byte) 0x50,
210        (byte) 0x72, (byte) 0xf8, (byte) 0x60, (byte) 0x13, (byte) 0xd8, (byte) 0xf1, (byte) 0x41, (byte) 0x01,
211        (byte) 0x10, (byte) 0xa5, (byte) 0x2f, (byte) 0x57, (byte) 0x5f,
212    });
213
214    private static final BigInteger DSA_G = new BigInteger(new byte[] {
215        (byte) 0x77, (byte) 0xd4, (byte) 0x7a, (byte) 0x12, (byte) 0xcc, (byte) 0x81, (byte) 0x7e, (byte) 0x7e,
216        (byte) 0xeb, (byte) 0x3a, (byte) 0xfb, (byte) 0xe6, (byte) 0x86, (byte) 0x6d, (byte) 0x5a, (byte) 0x10,
217        (byte) 0x1d, (byte) 0xad, (byte) 0xa9, (byte) 0x4f, (byte) 0xb9, (byte) 0x03, (byte) 0x5d, (byte) 0x21,
218        (byte) 0x1a, (byte) 0xe4, (byte) 0x30, (byte) 0x95, (byte) 0x75, (byte) 0x8e, (byte) 0xcd, (byte) 0x5e,
219        (byte) 0xd1, (byte) 0xbd, (byte) 0x0a, (byte) 0x45, (byte) 0xee, (byte) 0xe7, (byte) 0xf7, (byte) 0x6b,
220        (byte) 0x65, (byte) 0x02, (byte) 0x60, (byte) 0xd0, (byte) 0x2e, (byte) 0xaf, (byte) 0x3d, (byte) 0xbc,
221        (byte) 0x07, (byte) 0xdd, (byte) 0x2b, (byte) 0x8e, (byte) 0x33, (byte) 0xc0, (byte) 0x93, (byte) 0x80,
222        (byte) 0xd9, (byte) 0x2b, (byte) 0xa7, (byte) 0x71, (byte) 0x57, (byte) 0x76, (byte) 0xbc, (byte) 0x8e,
223        (byte) 0xb9, (byte) 0xe0, (byte) 0xd7, (byte) 0xf4, (byte) 0x23, (byte) 0x8d, (byte) 0x41, (byte) 0x1a,
224        (byte) 0x97, (byte) 0x4f, (byte) 0x2c, (byte) 0x1b, (byte) 0xd5, (byte) 0x4b, (byte) 0x66, (byte) 0xe8,
225        (byte) 0xfa, (byte) 0xd2, (byte) 0x50, (byte) 0x0d, (byte) 0x17, (byte) 0xab, (byte) 0x34, (byte) 0x31,
226        (byte) 0x3d, (byte) 0xa4, (byte) 0x88, (byte) 0xd8, (byte) 0x8e, (byte) 0xa8, (byte) 0xa7, (byte) 0x6e,
227        (byte) 0x17, (byte) 0x03, (byte) 0xb7, (byte) 0x0f, (byte) 0x68, (byte) 0x7c, (byte) 0x64, (byte) 0x7b,
228        (byte) 0x92, (byte) 0xb8, (byte) 0x63, (byte) 0xe4, (byte) 0x9a, (byte) 0x67, (byte) 0x18, (byte) 0x81,
229        (byte) 0x27, (byte) 0xd4, (byte) 0x0b, (byte) 0x13, (byte) 0x48, (byte) 0xd3, (byte) 0x7d, (byte) 0x4e,
230        (byte) 0xf6, (byte) 0xa8, (byte) 0x8f, (byte) 0x56, (byte) 0x17, (byte) 0x2d, (byte) 0x08, (byte) 0x51,
231    });
232
233    public void testDSAGeneratorWithParams() throws Exception {
234        final DSAParameterSpec dsaSpec = new DSAParameterSpec(DSA_P, DSA_Q, DSA_G);
235
236        boolean failure = false;
237
238        final Provider[] providers = Security.getProviders();
239        for (final Provider p : providers) {
240            Service s = p.getService("KeyPairGenerator", "DSA");
241            if (s == null) {
242                continue;
243            }
244
245            final KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA", p);
246            kpg.initialize(dsaSpec);
247            KeyPair pair = kpg.generateKeyPair();
248            DSAPrivateKey privKey = (DSAPrivateKey) pair.getPrivate();
249            DSAPublicKey pubKey = (DSAPublicKey) pair.getPublic();
250
251            DSAParams actualParams = privKey.getParams();
252            assertNotNull("DSA params should not be null", actualParams);
253
254            assertEquals("DSA P should be the same as supplied with provider " + p.getName(),
255                    DSA_P, actualParams.getP());
256            assertEquals("DSA Q should be the same as supplied with provider " + p.getName(),
257                    DSA_Q, actualParams.getQ());
258            assertEquals("DSA G should be the same as supplied with provider " + p.getName(),
259                    DSA_G, actualParams.getG());
260
261            actualParams = pubKey.getParams();
262            assertNotNull("DSA params should not be null", actualParams);
263
264            assertEquals("DSA P should be the same as supplied with provider " + p.getName(),
265                    DSA_P, actualParams.getP());
266            assertEquals("DSA Q should be the same as supplied with provider " + p.getName(),
267                    DSA_Q, actualParams.getQ());
268            assertEquals("DSA G should be the same as supplied with provider " + p.getName(),
269                    DSA_G, actualParams.getG());
270        }
271    }
272}
273