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