Home | History | Annotate | Download | only in jsse
      1 /*
      2  * Copyright (C) 2011 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 
     17 package org.apache.harmony.xnet.provider.jsse;
     18 
     19 import java.io.File;
     20 import java.io.FileOutputStream;
     21 import java.io.OutputStream;
     22 import java.security.KeyStore;
     23 import java.security.PrivateKey;
     24 import java.security.PublicKey;
     25 import java.security.cert.Certificate;
     26 import java.security.cert.X509Certificate;
     27 import java.util.Arrays;
     28 import java.util.Collections;
     29 import java.util.Enumeration;
     30 import java.util.HashSet;
     31 import java.util.List;
     32 import java.util.NoSuchElementException;
     33 import java.util.Set;
     34 import javax.security.auth.x500.X500Principal;
     35 import junit.framework.TestCase;
     36 import libcore.java.security.TestKeyStore;
     37 
     38 public class TrustedCertificateStoreTest extends TestCase {
     39 
     40     private static final File DIR_TEMP = new File(System.getProperty("java.io.tmpdir"));
     41     private static final File DIR_TEST = new File(DIR_TEMP, "test");
     42     private static final File DIR_SYSTEM = new File(DIR_TEST, "system");
     43     private static final File DIR_ADDED = new File(DIR_TEST, "added");
     44     private static final File DIR_DELETED = new File(DIR_TEST, "removed");
     45 
     46     private static X509Certificate CA1;
     47     private static X509Certificate CA2;
     48 
     49     private static KeyStore.PrivateKeyEntry PRIVATE;
     50     private static X509Certificate[] CHAIN;
     51 
     52     private static X509Certificate CA3_WITH_CA1_SUBJECT;
     53     private static String ALIAS_SYSTEM_CA1;
     54     private static String ALIAS_SYSTEM_CA2;
     55     private static String ALIAS_USER_CA1;
     56     private static String ALIAS_USER_CA2;
     57 
     58     private static String ALIAS_SYSTEM_CHAIN0;
     59     private static String ALIAS_SYSTEM_CHAIN1;
     60     private static String ALIAS_SYSTEM_CHAIN2;
     61     private static String ALIAS_USER_CHAIN0;
     62     private static String ALIAS_USER_CHAIN1;
     63     private static String ALIAS_USER_CHAIN2;
     64 
     65     private static String ALIAS_SYSTEM_CA3;
     66     private static String ALIAS_SYSTEM_CA3_COLLISION;
     67     private static String ALIAS_USER_CA3;
     68     private static String ALIAS_USER_CA3_COLLISION;
     69 
     70     private static X509Certificate getCa1() {
     71         initCerts();
     72         return CA1;
     73     }
     74     private static X509Certificate getCa2() {
     75         initCerts();
     76         return CA2;
     77     }
     78 
     79     private static KeyStore.PrivateKeyEntry getPrivate() {
     80         initCerts();
     81         return PRIVATE;
     82     }
     83     private static X509Certificate[] getChain() {
     84         initCerts();
     85         return CHAIN;
     86     }
     87 
     88     private static X509Certificate getCa3WithCa1Subject() {
     89         initCerts();
     90         return CA3_WITH_CA1_SUBJECT;
     91     }
     92 
     93     private static String getAliasSystemCa1() {
     94         initCerts();
     95         return ALIAS_SYSTEM_CA1;
     96     }
     97     private static String getAliasSystemCa2() {
     98         initCerts();
     99         return ALIAS_SYSTEM_CA2;
    100     }
    101     private static String getAliasUserCa1() {
    102         initCerts();
    103         return ALIAS_USER_CA1;
    104     }
    105     private static String getAliasUserCa2() {
    106         initCerts();
    107         return ALIAS_USER_CA2;
    108     }
    109 
    110     private static String getAliasSystemChain0() {
    111         initCerts();
    112         return ALIAS_SYSTEM_CHAIN0;
    113     }
    114     private static String getAliasSystemChain1() {
    115         initCerts();
    116         return ALIAS_SYSTEM_CHAIN1;
    117     }
    118     private static String getAliasSystemChain2() {
    119         initCerts();
    120         return ALIAS_SYSTEM_CHAIN2;
    121     }
    122     private static String getAliasUserChain0() {
    123         initCerts();
    124         return ALIAS_USER_CHAIN0;
    125     }
    126     private static String getAliasUserChain1() {
    127         initCerts();
    128         return ALIAS_USER_CHAIN1;
    129     }
    130     private static String getAliasUserChain2() {
    131         initCerts();
    132         return ALIAS_USER_CHAIN2;
    133     }
    134 
    135     private static String getAliasSystemCa3() {
    136         initCerts();
    137         return ALIAS_SYSTEM_CA3;
    138     }
    139     private static String getAliasSystemCa3Collision() {
    140         initCerts();
    141         return ALIAS_SYSTEM_CA3_COLLISION;
    142     }
    143     private static String getAliasUserCa3() {
    144         initCerts();
    145         return ALIAS_USER_CA3;
    146     }
    147     private static String getAliasUserCa3Collision() {
    148         initCerts();
    149         return ALIAS_USER_CA3_COLLISION;
    150     }
    151 
    152     /**
    153      * Lazily create shared test certificates.
    154      */
    155     private static synchronized void initCerts() {
    156         if (CA1 != null) {
    157             return;
    158         }
    159         try {
    160             CA1 = TestKeyStore.getClient().getRootCertificate("RSA");
    161             CA2 = TestKeyStore.getClientCA2().getRootCertificate("RSA");
    162             PRIVATE = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
    163             CHAIN = (X509Certificate[]) PRIVATE.getCertificateChain();
    164             CA3_WITH_CA1_SUBJECT = new TestKeyStore.Builder()
    165                     .aliasPrefix("unused")
    166                     .subject(CA1.getSubjectX500Principal())
    167                     .ca(true)
    168                     .build().getRootCertificate("RSA");
    169 
    170 
    171             ALIAS_SYSTEM_CA1 = alias(false, CA1, 0);
    172             ALIAS_SYSTEM_CA2 = alias(false, CA2, 0);
    173             ALIAS_USER_CA1 = alias(true, CA1, 0);
    174             ALIAS_USER_CA2 = alias(true, CA2, 0);
    175 
    176             ALIAS_SYSTEM_CHAIN0 = alias(false, getChain()[0], 0);
    177             ALIAS_SYSTEM_CHAIN1 = alias(false, getChain()[1], 0);
    178             ALIAS_SYSTEM_CHAIN2 = alias(false, getChain()[2], 0);
    179             ALIAS_USER_CHAIN0 = alias(true, getChain()[0], 0);
    180             ALIAS_USER_CHAIN1 = alias(true, getChain()[1], 0);
    181             ALIAS_USER_CHAIN2 = alias(true, getChain()[2], 0);
    182 
    183             ALIAS_SYSTEM_CA3 = alias(false, CA3_WITH_CA1_SUBJECT, 0);
    184             ALIAS_SYSTEM_CA3_COLLISION = alias(false, CA3_WITH_CA1_SUBJECT, 1);
    185             ALIAS_USER_CA3 = alias(true, CA3_WITH_CA1_SUBJECT, 0);
    186             ALIAS_USER_CA3_COLLISION = alias(true, CA3_WITH_CA1_SUBJECT, 1);
    187         } catch (Exception e) {
    188             throw new RuntimeException(e);
    189         }
    190     }
    191 
    192     private TrustedCertificateStore store;
    193 
    194     @Override protected void setUp() {
    195         setupStore();
    196     }
    197 
    198     private void setupStore() {
    199         DIR_SYSTEM.mkdirs();
    200         createStore();
    201     }
    202 
    203     private void createStore() {
    204         store = new TrustedCertificateStore(DIR_SYSTEM, DIR_ADDED, DIR_DELETED);
    205     }
    206 
    207     @Override protected void tearDown() {
    208         cleanStore();
    209     }
    210 
    211     private void cleanStore() {
    212         for (File dir : new File[] { DIR_SYSTEM, DIR_ADDED, DIR_DELETED, DIR_TEST }) {
    213             File[] files = dir.listFiles();
    214             if (files == null) {
    215                 continue;
    216             }
    217             for (File file : files) {
    218                 assertTrue(file.delete());
    219             }
    220         }
    221         store = null;
    222     }
    223 
    224     private void resetStore() {
    225         cleanStore();
    226         setupStore();
    227     }
    228 
    229     public void testEmptyDirectories() throws Exception {
    230         assertEmpty();
    231     }
    232 
    233     public void testOneSystemOneDeleted() throws Exception {
    234         install(getCa1(), getAliasSystemCa1());
    235         store.deleteCertificateEntry(getAliasSystemCa1());
    236         assertEmpty();
    237         assertDeleted(getCa1(), getAliasSystemCa1());
    238     }
    239 
    240     public void testTwoSystemTwoDeleted() throws Exception {
    241         install(getCa1(), getAliasSystemCa1());
    242         store.deleteCertificateEntry(getAliasSystemCa1());
    243         install(getCa2(), getAliasSystemCa2());
    244         store.deleteCertificateEntry(getAliasSystemCa2());
    245         assertEmpty();
    246         assertDeleted(getCa1(), getAliasSystemCa1());
    247         assertDeleted(getCa2(), getAliasSystemCa2());
    248     }
    249 
    250     public void testPartialFileIsIgnored() throws Exception {
    251         File file = file(getAliasSystemCa1());
    252         OutputStream os = new FileOutputStream(file);
    253         os.write(0);
    254         os.close();
    255         assertTrue(file.exists());
    256         assertEmpty();
    257         assertTrue(file.exists());
    258     }
    259 
    260     private void assertEmpty() throws Exception {
    261         try {
    262             store.getCertificate(null);
    263             fail();
    264         } catch (NullPointerException expected) {
    265         }
    266         assertNull(store.getCertificate(""));
    267 
    268         try {
    269             store.getCreationDate(null);
    270             fail();
    271         } catch (NullPointerException expected) {
    272         }
    273         assertNull(store.getCreationDate(""));
    274 
    275         Set<String> s = store.aliases();
    276         assertNotNull(s);
    277         assertTrue(s.isEmpty());
    278         assertAliases();
    279 
    280         Set<String> u = store.userAliases();
    281         assertNotNull(u);
    282         assertTrue(u.isEmpty());
    283 
    284         try {
    285             store.containsAlias(null);
    286             fail();
    287         } catch (NullPointerException expected) {
    288         }
    289         assertFalse(store.containsAlias(""));
    290 
    291         assertNull(store.getCertificateAlias(null));
    292         assertNull(store.getCertificateAlias(getCa1()));
    293 
    294         try {
    295             store.isTrustAnchor(null);
    296             fail();
    297         } catch (NullPointerException expected) {
    298         }
    299         assertFalse(store.isTrustAnchor(getCa1()));
    300 
    301         try {
    302             store.findIssuer(null);
    303             fail();
    304         } catch (NullPointerException expected) {
    305         }
    306         assertNull(store.findIssuer(getCa1()));
    307 
    308         try {
    309             store.installCertificate(null);
    310             fail();
    311         } catch (NullPointerException expected) {
    312         }
    313 
    314         store.deleteCertificateEntry(null);
    315         store.deleteCertificateEntry("");
    316 
    317         String[] userFiles = DIR_ADDED.list();
    318         assertTrue(userFiles == null || userFiles.length == 0);
    319     }
    320 
    321     public void testTwoSystem() throws Exception {
    322         testTwo(getCa1(), getAliasSystemCa1(),
    323                 getCa2(), getAliasSystemCa2());
    324     }
    325 
    326     public void testTwoUser() throws Exception {
    327         testTwo(getCa1(), getAliasUserCa1(),
    328                 getCa2(), getAliasUserCa2());
    329     }
    330 
    331     public void testOneSystemOneUser() throws Exception {
    332         testTwo(getCa1(), getAliasSystemCa1(),
    333                 getCa2(), getAliasUserCa2());
    334     }
    335 
    336     public void testTwoSystemSameSubject() throws Exception {
    337         testTwo(getCa1(), getAliasSystemCa1(),
    338                 getCa3WithCa1Subject(), getAliasSystemCa3Collision());
    339     }
    340 
    341     public void testTwoUserSameSubject() throws Exception {
    342         testTwo(getCa1(), getAliasUserCa1(),
    343                 getCa3WithCa1Subject(), getAliasUserCa3Collision());
    344 
    345         store.deleteCertificateEntry(getAliasUserCa1());
    346         assertDeleted(getCa1(), getAliasUserCa1());
    347         assertTombstone(getAliasUserCa1());
    348         assertRootCa(getCa3WithCa1Subject(), getAliasUserCa3Collision());
    349         assertAliases(getAliasUserCa3Collision());
    350 
    351         store.deleteCertificateEntry(getAliasUserCa3Collision());
    352         assertDeleted(getCa3WithCa1Subject(), getAliasUserCa3Collision());
    353         assertNoTombstone(getAliasUserCa3Collision());
    354         assertNoTombstone(getAliasUserCa1());
    355         assertEmpty();
    356     }
    357 
    358     public void testOneSystemOneUserSameSubject() throws Exception {
    359         testTwo(getCa1(), getAliasSystemCa1(),
    360                 getCa3WithCa1Subject(), getAliasUserCa3());
    361         testTwo(getCa1(), getAliasUserCa1(),
    362                 getCa3WithCa1Subject(), getAliasSystemCa3());
    363     }
    364 
    365     private void testTwo(X509Certificate x1, String alias1,
    366                          X509Certificate x2, String alias2) {
    367         install(x1, alias1);
    368         install(x2, alias2);
    369         assertRootCa(x1, alias1);
    370         assertRootCa(x2, alias2);
    371         assertAliases(alias1, alias2);
    372     }
    373 
    374 
    375     public void testOneSystemOneUserOneDeleted() throws Exception {
    376         install(getCa1(), getAliasSystemCa1());
    377         store.installCertificate(getCa2());
    378         store.deleteCertificateEntry(getAliasSystemCa1());
    379         assertDeleted(getCa1(), getAliasSystemCa1());
    380         assertRootCa(getCa2(), getAliasUserCa2());
    381         assertAliases(getAliasUserCa2());
    382     }
    383 
    384     public void testOneSystemOneUserOneDeletedSameSubject() throws Exception {
    385         install(getCa1(), getAliasSystemCa1());
    386         store.installCertificate(getCa3WithCa1Subject());
    387         store.deleteCertificateEntry(getAliasSystemCa1());
    388         assertDeleted(getCa1(), getAliasSystemCa1());
    389         assertRootCa(getCa3WithCa1Subject(), getAliasUserCa3());
    390         assertAliases(getAliasUserCa3());
    391     }
    392 
    393     public void testUserMaskingSystem() throws Exception {
    394         install(getCa1(), getAliasSystemCa1());
    395         install(getCa1(), getAliasUserCa1());
    396         assertMasked(getCa1(), getAliasSystemCa1());
    397         assertRootCa(getCa1(), getAliasUserCa1());
    398         assertAliases(getAliasSystemCa1(), getAliasUserCa1());
    399     }
    400 
    401     public void testChain() throws Exception {
    402         testChain(getAliasSystemChain1(), getAliasSystemChain2());
    403         testChain(getAliasSystemChain1(), getAliasUserChain2());
    404         testChain(getAliasUserChain1(), getAliasSystemCa1());
    405         testChain(getAliasUserChain1(), getAliasUserChain2());
    406     }
    407 
    408     private void testChain(String alias1, String alias2) throws Exception {
    409         install(getChain()[1], alias1);
    410         install(getChain()[2], alias2);
    411         assertIntermediateCa(getChain()[1], alias1);
    412         assertRootCa(getChain()[2], alias2);
    413         assertAliases(alias1, alias2);
    414         assertEquals(getChain()[2], store.findIssuer(getChain()[1]));
    415         assertEquals(getChain()[1], store.findIssuer(getChain()[0]));
    416 
    417         X509Certificate[] expected = getChain();
    418         List<X509Certificate> actualList = store.getCertificateChain(expected[0]);
    419 
    420         assertEquals("Generated CA list should be same length", expected.length, actualList.size());
    421         for (int i = 0; i < expected.length; i++) {
    422             assertEquals("Chain value should be the same for position " + i, expected[i],
    423                     actualList.get(i));
    424         }
    425         resetStore();
    426     }
    427 
    428     public void testMissingSystemDirectory() throws Exception {
    429         cleanStore();
    430         createStore();
    431         assertEmpty();
    432     }
    433 
    434     public void testWithExistingUserDirectories() throws Exception {
    435         DIR_ADDED.mkdirs();
    436         DIR_DELETED.mkdirs();
    437         install(getCa1(), getAliasSystemCa1());
    438         assertRootCa(getCa1(), getAliasSystemCa1());
    439         assertAliases(getAliasSystemCa1());
    440     }
    441 
    442     public void testIsTrustAnchorWithReissuedgetCa() throws Exception {
    443         PublicKey publicKey = getPrivate().getCertificate().getPublicKey();
    444         PrivateKey privateKey = getPrivate().getPrivateKey();
    445         String name = "CN=CA4";
    446         X509Certificate ca1 = TestKeyStore.createCa(publicKey, privateKey, name);
    447         Thread.sleep(1 * 1000); // wait to ensure CAs vary by expiration
    448         X509Certificate ca2 = TestKeyStore.createCa(publicKey, privateKey, name);
    449         assertFalse(ca1.equals(ca2));
    450 
    451         String systemAlias = alias(false, ca1, 0);
    452         install(ca1, systemAlias);
    453         assertRootCa(ca1, systemAlias);
    454         assertTrue(store.isTrustAnchor(ca2));
    455         assertEquals(ca1, store.findIssuer(ca2));
    456         resetStore();
    457 
    458         String userAlias = alias(true, ca1, 0);
    459         store.installCertificate(ca1);
    460         assertRootCa(ca1, userAlias);
    461         assertTrue(store.isTrustAnchor(ca2));
    462         assertEquals(ca1, store.findIssuer(ca2));
    463         resetStore();
    464     }
    465 
    466     public void testInstallEmpty() throws Exception {
    467         store.installCertificate(getCa1());
    468         assertRootCa(getCa1(), getAliasUserCa1());
    469         assertAliases(getAliasUserCa1());
    470 
    471         // reinstalling should not change anything
    472         store.installCertificate(getCa1());
    473         assertRootCa(getCa1(), getAliasUserCa1());
    474         assertAliases(getAliasUserCa1());
    475     }
    476 
    477     public void testInstallEmptySystemExists() throws Exception {
    478         install(getCa1(), getAliasSystemCa1());
    479         assertRootCa(getCa1(), getAliasSystemCa1());
    480         assertAliases(getAliasSystemCa1());
    481 
    482         // reinstalling should not affect system CA
    483         store.installCertificate(getCa1());
    484         assertRootCa(getCa1(), getAliasSystemCa1());
    485         assertAliases(getAliasSystemCa1());
    486 
    487     }
    488 
    489     public void testInstallEmptyDeletedSystemExists() throws Exception {
    490         install(getCa1(), getAliasSystemCa1());
    491         store.deleteCertificateEntry(getAliasSystemCa1());
    492         assertEmpty();
    493         assertDeleted(getCa1(), getAliasSystemCa1());
    494 
    495         // installing should restore deleted system CA
    496         store.installCertificate(getCa1());
    497         assertRootCa(getCa1(), getAliasSystemCa1());
    498         assertAliases(getAliasSystemCa1());
    499     }
    500 
    501     public void testDeleteEmpty() throws Exception {
    502         store.deleteCertificateEntry(getAliasSystemCa1());
    503         assertEmpty();
    504         assertDeleted(getCa1(), getAliasSystemCa1());
    505     }
    506 
    507     public void testDeleteUser() throws Exception {
    508         store.installCertificate(getCa1());
    509         assertRootCa(getCa1(), getAliasUserCa1());
    510         assertAliases(getAliasUserCa1());
    511 
    512         store.deleteCertificateEntry(getAliasUserCa1());
    513         assertEmpty();
    514         assertDeleted(getCa1(), getAliasUserCa1());
    515         assertNoTombstone(getAliasUserCa1());
    516     }
    517 
    518     public void testDeleteSystem() throws Exception {
    519         install(getCa1(), getAliasSystemCa1());
    520         assertRootCa(getCa1(), getAliasSystemCa1());
    521         assertAliases(getAliasSystemCa1());
    522 
    523         store.deleteCertificateEntry(getAliasSystemCa1());
    524         assertEmpty();
    525         assertDeleted(getCa1(), getAliasSystemCa1());
    526 
    527         // deleting again should not change anything
    528         store.deleteCertificateEntry(getAliasSystemCa1());
    529         assertEmpty();
    530         assertDeleted(getCa1(), getAliasSystemCa1());
    531     }
    532 
    533     public void testIsUserAddedCertificate() throws Exception {
    534         assertFalse(store.isUserAddedCertificate(getCa1()));
    535         assertFalse(store.isUserAddedCertificate(getCa2()));
    536         install(getCa1(), getAliasSystemCa1());
    537         assertFalse(store.isUserAddedCertificate(getCa1()));
    538         assertFalse(store.isUserAddedCertificate(getCa2()));
    539         install(getCa1(), getAliasUserCa1());
    540         assertTrue(store.isUserAddedCertificate(getCa1()));
    541         assertFalse(store.isUserAddedCertificate(getCa2()));
    542         install(getCa2(), getAliasUserCa2());
    543         assertTrue(store.isUserAddedCertificate(getCa1()));
    544         assertTrue(store.isUserAddedCertificate(getCa2()));
    545         store.deleteCertificateEntry(getAliasUserCa1());
    546         assertFalse(store.isUserAddedCertificate(getCa1()));
    547         assertTrue(store.isUserAddedCertificate(getCa2()));
    548         store.deleteCertificateEntry(getAliasUserCa2());
    549         assertFalse(store.isUserAddedCertificate(getCa1()));
    550         assertFalse(store.isUserAddedCertificate(getCa2()));
    551     }
    552 
    553     private void assertRootCa(X509Certificate x, String alias) {
    554         assertIntermediateCa(x, alias);
    555         assertEquals(x, store.findIssuer(x));
    556     }
    557 
    558     private void assertTrusted(X509Certificate x, String alias) {
    559         assertEquals(x, store.getCertificate(alias));
    560         assertEquals(file(alias).lastModified(), store.getCreationDate(alias).getTime());
    561         assertTrue(store.containsAlias(alias));
    562         assertTrue(store.isTrustAnchor(x));
    563     }
    564 
    565     private void assertIntermediateCa(X509Certificate x, String alias) {
    566         assertTrusted(x, alias);
    567         assertEquals(alias, store.getCertificateAlias(x));
    568     }
    569 
    570     private void assertMasked(X509Certificate x, String alias) {
    571         assertTrusted(x, alias);
    572         assertFalse(alias.equals(store.getCertificateAlias(x)));
    573     }
    574 
    575     private void assertDeleted(X509Certificate x, String alias) {
    576         assertNull(store.getCertificate(alias));
    577         assertFalse(store.containsAlias(alias));
    578         assertNull(store.getCertificateAlias(x));
    579         assertFalse(store.isTrustAnchor(x));
    580         assertEquals(store.allSystemAliases().contains(alias),
    581                      store.getCertificate(alias, true) != null);
    582     }
    583 
    584     private void assertTombstone(String alias) {
    585         assertTrue(TrustedCertificateStore.isUser(alias));
    586         File file = file(alias);
    587         assertTrue(file.exists());
    588         assertEquals(0, file.length());
    589     }
    590 
    591     private void assertNoTombstone(String alias) {
    592         assertTrue(TrustedCertificateStore.isUser(alias));
    593         assertFalse(file(alias).exists());
    594     }
    595 
    596     private void assertAliases(String... aliases) {
    597         Set<String> expected = new HashSet<String>(Arrays.asList(aliases));
    598         Set<String> actual = new HashSet<String>();
    599         for (String alias : store.aliases()) {
    600             boolean system = TrustedCertificateStore.isSystem(alias);
    601             boolean user = TrustedCertificateStore.isUser(alias);
    602             if (system || user) {
    603                 assertEquals(system, store.allSystemAliases().contains(alias));
    604                 assertEquals(user, store.userAliases().contains(alias));
    605                 actual.add(alias);
    606             } else {
    607                 throw new AssertionError(alias);
    608             }
    609         }
    610         assertEquals(expected, actual);
    611     }
    612 
    613     /**
    614      * format a certificate alias
    615      */
    616     private static String alias(boolean user, X509Certificate x, int index) {
    617         String prefix = user ? "user:" : "system:";
    618 
    619         X500Principal subject = x.getSubjectX500Principal();
    620         int intHash = NativeCrypto.X509_NAME_hash_old(subject);
    621         String strHash = IntegralToString.intToHexString(intHash, false, 8);
    622 
    623         return prefix + strHash + '.' + index;
    624     }
    625 
    626     /**
    627      * Install certificate under specified alias
    628      */
    629     private static void install(X509Certificate x, String alias) {
    630         try {
    631             File file = file(alias);
    632             file.getParentFile().mkdirs();
    633             OutputStream out = new FileOutputStream(file);
    634             out.write(x.getEncoded());
    635             out.close();
    636         } catch (Exception e) {
    637             throw new RuntimeException(e);
    638         }
    639     }
    640 
    641     /**
    642      * Compute file for an alias
    643      */
    644     private static File file(String alias) {
    645         File dir;
    646         if (TrustedCertificateStore.isSystem(alias)) {
    647             dir = DIR_SYSTEM;
    648         } else if (TrustedCertificateStore.isUser(alias)) {
    649             dir = DIR_ADDED;
    650         } else {
    651             throw new IllegalArgumentException(alias);
    652         }
    653 
    654         int index = alias.lastIndexOf(":");
    655         if (index == -1) {
    656             throw new IllegalArgumentException(alias);
    657         }
    658         String filename = alias.substring(index+1);
    659 
    660         return new File(dir, filename);
    661     }
    662 }
    663