AndroidKeyPairGeneratorTest.java revision 78ad849163a7b01073b46fbd7d818392720005d1
1db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root/*
2db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Copyright (C) 2012 The Android Open Source Project
3db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
4db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * you may not use this file except in compliance with the License.
6db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * You may obtain a copy of the License at
7db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
8db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
10db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Unless required by applicable law or agreed to in writing, software
11db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * See the License for the specific language governing permissions and
14db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * limitations under the License.
15db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root */
16db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
17db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootpackage android.security;
18db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
19db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport android.test.AndroidTestCase;
20db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
21db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.io.ByteArrayInputStream;
22db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.math.BigInteger;
23db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.KeyPair;
24db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.PrivateKey;
25db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.PublicKey;
26db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.SecureRandom;
27db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.cert.Certificate;
28db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.cert.CertificateFactory;
29db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.cert.X509Certificate;
30db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.util.Date;
31db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
32db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport javax.security.auth.x500.X500Principal;
33db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
34db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootpublic class AndroidKeyPairGeneratorTest extends AndroidTestCase {
35db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private android.security.KeyStore mAndroidKeyStore;
36db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
37db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private java.security.KeyPairGenerator mGenerator;
38db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
39db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final String TEST_ALIAS_1 = "test1";
40db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
41db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final String TEST_ALIAS_2 = "test2";
42db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
43db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
44db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
45db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2");
46db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
47db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE;
48db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
49db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L);
50db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
51db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final long NOW_MILLIS = System.currentTimeMillis();
52db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
53db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    /* We have to round this off because X509v3 doesn't store milliseconds. */
54db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
55db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
56db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    @SuppressWarnings("deprecation")
57db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
58db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
59db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    @Override
60db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    protected void setUp() throws Exception {
61db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mAndroidKeyStore = android.security.KeyStore.getInstance();
62db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
63db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertTrue(mAndroidKeyStore.reset());
64db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
65b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root        assertFalse(mAndroidKeyStore.isUnlocked());
66db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
67db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertTrue(mAndroidKeyStore.password("1111"));
68b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root        assertTrue(mAndroidKeyStore.isUnlocked());
69db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
7078ad849163a7b01073b46fbd7d818392720005d1Kenny Root        String[] aliases = mAndroidKeyStore.saw("");
7178ad849163a7b01073b46fbd7d818392720005d1Kenny Root        assertNotNull(aliases);
7278ad849163a7b01073b46fbd7d818392720005d1Kenny Root        assertEquals(0, aliases.length);
73db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
74db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mGenerator = java.security.KeyPairGenerator.getInstance(AndroidKeyPairGenerator.NAME);
75db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
76db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
77db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void testKeyPairGenerator_Initialize_Params_Success() throws Exception {
78db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
79db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
80db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
81db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
82db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void testKeyPairGenerator_Initialize_KeySize_Failure() throws Exception {
83db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        try {
84db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            mGenerator.initialize(1024);
85db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            fail("KeyPairGenerator should not support setting the key size");
86db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (IllegalArgumentException success) {
87db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
88db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
89db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
90db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void testKeyPairGenerator_Initialize_KeySizeAndSecureRandom_Failure() throws Exception {
91db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        try {
92db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            mGenerator.initialize(1024, new SecureRandom());
93db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            fail("KeyPairGenerator should not support setting the key size");
94db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (IllegalArgumentException success) {
95db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
96db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
97db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
98db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void testKeyPairGenerator_Initialize_ParamsAndSecureRandom_Failure() throws Exception {
99db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
100db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS), new SecureRandom());
101db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
102db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
103db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void testKeyPairGenerator_GenerateKeyPair_Success() throws Exception {
104db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
105db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
106db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
107db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final KeyPair pair = mGenerator.generateKeyPair();
108db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertNotNull("The KeyPair returned should not be null", pair);
109db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
110db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertKeyPairCorrect(pair, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS);
111db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
112db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
113db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void testKeyPairGenerator_GenerateKeyPair_Replaced_Success() throws Exception {
114db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        // Generate the first key
115db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        {
116db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
117db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                    TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
118db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            final KeyPair pair1 = mGenerator.generateKeyPair();
119db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            assertNotNull("The KeyPair returned should not be null", pair1);
120db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            assertKeyPairCorrect(pair1, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW,
121db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                    NOW_PLUS_10_YEARS);
122db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
123db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
124db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        // Replace the original key
125db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        {
126db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_2,
127db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                    TEST_DN_2, TEST_SERIAL_2, NOW, NOW_PLUS_10_YEARS));
128db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            final KeyPair pair2 = mGenerator.generateKeyPair();
129db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            assertNotNull("The KeyPair returned should not be null", pair2);
130db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            assertKeyPairCorrect(pair2, TEST_ALIAS_2, TEST_DN_2, TEST_SERIAL_2, NOW,
131db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                    NOW_PLUS_10_YEARS);
132db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
133db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
134db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
135db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private void assertKeyPairCorrect(KeyPair pair, String alias, X500Principal dn,
136db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            BigInteger serial, Date start, Date end) throws Exception {
137db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final PublicKey pubKey = pair.getPublic();
138db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertNotNull("The PublicKey for the KeyPair should be not null", pubKey);
139db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
140db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final PrivateKey privKey = pair.getPrivate();
141db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertNotNull("The PrivateKey for the KeyPair should be not null", privKey);
142db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
143db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final byte[] userCertBytes = mAndroidKeyStore.get(Credentials.USER_CERTIFICATE + alias);
144db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertNotNull("The user certificate should exist for the generated entry", userCertBytes);
145db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
146db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
147db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final Certificate userCert = cf
148db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                .generateCertificate(new ByteArrayInputStream(userCertBytes));
149db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
150db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertTrue("Certificate should be in X.509 format", userCert instanceof X509Certificate);
151db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
152db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final X509Certificate x509userCert = (X509Certificate) userCert;
153db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
154db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertEquals("PublicKey used to sign certificate should match one returned in KeyPair",
155db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                pubKey, x509userCert.getPublicKey());
156db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
157db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertEquals("The Subject DN should be the one passed into the params", dn,
158db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                x509userCert.getSubjectDN());
159db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
160db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertEquals("The Issuer DN should be the same as the Subject DN", dn,
161db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                x509userCert.getIssuerDN());
162db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
163db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertEquals("The Serial should be the one passed into the params", serial,
164db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                x509userCert.getSerialNumber());
165db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
166db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertEquals("The notBefore date should be the one passed into the params", start,
167db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                x509userCert.getNotBefore());
168db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
169db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertEquals("The notAfter date should be the one passed into the params", end,
170db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                x509userCert.getNotAfter());
171db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
172db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        x509userCert.verify(pubKey);
173db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
174db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final byte[] caCerts = mAndroidKeyStore.get(Credentials.CA_CERTIFICATE + alias);
175db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertNull("A list of CA certificates should not exist for the generated entry", caCerts);
176db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
177db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final byte[] pubKeyBytes = mAndroidKeyStore.getPubkey(Credentials.USER_PRIVATE_KEY + alias);
178db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        assertNotNull("The keystore should return the public key for the generated key",
179db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root                pubKeyBytes);
180db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
181db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root}
182