source: dispositivos_moviles/TibisayMovil/src/ve/gob/cenditel/tibisaymovil/DirectKeyChain.java @ 42e7061

Last change on this file since 42e7061 was 6141013, checked in by Jose Ruiz <joseruiz@…>, 11 years ago

Corrección de error en el repositorio de certificados 'Sin acceso al repositorio'

  • Property mode set to 100644
File size: 14.8 KB
Line 
1package ve.gob.cenditel.tibisaymovil;
2
3import java.io.FileNotFoundException;
4import java.io.IOException;
5import java.io.InputStream;
6import java.security.KeyStore;
7import java.security.KeyStore.PrivateKeyEntry;
8import java.security.KeyStoreException;
9import java.security.NoSuchAlgorithmException;
10import java.security.PrivateKey;
11import java.security.cert.Certificate;
12import java.security.cert.CertificateException;
13import java.security.cert.X509Certificate;
14import java.util.Enumeration;
15
16
17import android.app.Activity;
18import android.content.Context;
19import android.content.DialogInterface;
20import android.net.Uri;
21import android.util.Log;
22import android.view.View;
23import android.widget.ListView;
24import android.widget.Toast;
25
26public class DirectKeyChain { 
27
28    private static final long serialVersionUID = 5677500714263795351L;
29
30    private static final String keyStoreType = "BCPKCS12";
31    static final String keyStoreFilename = ".keystore";
32    private static KeyStore keystore = null;
33    private static String password = null;
34   
35
36        private static DirectKeyChain theInstance;
37
38        private Activity master;
39
40        private boolean buttonsKeyStoreStatus;
41
42        public boolean isButtonsKeyStoreStatus() {
43                return buttonsKeyStoreStatus;
44        }
45
46        public void setButtonsKeyStoreStatus(boolean buttonsKeyStoreStatus) {
47                this.buttonsKeyStoreStatus = buttonsKeyStoreStatus;
48        }
49
50
51        private ListView listView;
52
53        public DirectCertificateAdapter adapter;
54
55//      private MainBarClickListener mainbar;
56       
57        private DirectKeyChain() {
58        }
59       
60    private DirectKeyChain(Activity master) {
61        this.master=master;
62    }
63   
64    public void setMasterActivity(Activity master){this.master=master;}
65
66
67    public static DirectKeyChain getInstance() {
68
69        if (DirectKeyChain.theInstance == null) {
70
71                DirectKeyChain.theInstance = new DirectKeyChain();
72        }
73        return (DirectKeyChain) DirectKeyChain.theInstance;
74    }
75
76    public void choosePrivateKeyAlias() {
77
78        if (!keystoreExists()) {
79            createKeystoreAndChoosePrivateKeyAlias();
80        } else {
81            if (DirectKeyChain.keystore == null) {
82                openKeystoreAndChoosePrivateKeyAlias();
83            } else {
84                startKeyChainActivityAndChoosePrivateKeyAlias();
85            }
86        }
87     
88    }
89
90    public void openOrCreateKeyAlias() {
91
92      DirectKeyChain.keystore=null;
93      choosePrivateKeyAlias();
94       
95    }
96               
97    public X509Certificate[] getCertificateChain(String alias)
98    throws KeystoreException {
99
100        checkKeystoreOpen();
101        try {
102            KeyStore trusted = getKeystore();
103            Certificate[] chain = trusted.getCertificateChain(alias);
104            X509Certificate[] result = new X509Certificate[chain.length];
105            for(int i = 0; i < chain.length; i++) {
106                // Casting chain to X509Certificate[] seems to be not enough
107                result[i] = (X509Certificate) chain[i];
108            }
109            return result;
110        } catch (Exception e) {
111            throw new KeystoreException(e);
112        }
113    }
114
115    public PrivateKey getPrivateKey(String alias)
116    throws KeystoreException {
117
118        checkKeystoreOpen();
119        try {
120            KeyStore trusted = getKeystore();
121            return ((PrivateKeyEntry) trusted.getEntry(alias, null)).getPrivateKey();
122        } catch (Exception e) {
123            throw new KeystoreException(e);
124        }
125    }
126   
127   
128   
129        public int deleteCertificate(String alias) throws KeystoreException{
130               
131                try {
132                        KeyStore trusted = getKeystore();
133                trusted.deleteEntry(alias);
134                } catch (Exception e) {
135                        throw new KeystoreException(e);
136                }
137               
138                if (this.adapter!=null)this.adapter.notifyDataSetChanged();
139                return 0;
140               
141        }
142   
143   
144
145    public Enumeration<String> getAliases()
146    throws KeystoreException {
147
148        try {
149            KeyStore trusted = getKeystore();
150            return new PrivateKeyEnumeration(trusted);
151        } catch (KeyStoreException e) {
152            throw new KeystoreException(e);
153        }
154    }
155
156    public int importCertificate(Uri file, String password)
157    throws KeystoreException {
158
159        try {
160            KeyStore trusted = getKeystore();
161            KeyStore p12 = KeyStore.getInstance("PKCS12");
162            InputStream stream = this.master.getContentResolver().openInputStream(file);
163            p12.load(stream, password.toCharArray());
164            stream.close();
165            Enumeration<String> aliases = p12.aliases();
166            int imported = 0;
167            while (aliases.hasMoreElements()) {
168                String alias = aliases.nextElement();
169                if (p12.isKeyEntry(alias)) {
170                    Certificate[] chain = p12.getCertificateChain(alias);
171                    for (Certificate cert : chain) {
172                        if (!(cert instanceof X509Certificate)) {
173                            throw new KeyStoreException();
174                        }
175                    }
176                    // TODO allow to import with a diferent alias. Warn if alias already exists
177                    trusted.setKeyEntry(alias, p12.getKey(alias, null), null, chain);
178                    imported++;
179                }
180            }
181            return imported;
182        } catch (Exception e) {
183            IncorrectPasswordException.checkException(e);
184            throw new KeystoreException(e);
185        }
186    }
187
188    public void saveKeystore()
189    throws KeystoreException, OutOfSpaceError {
190
191        saveKeystore(DirectKeyChain.password);
192    }
193
194    public void saveKeystore(String password)
195    throws KeystoreException, OutOfSpaceError {
196
197        try {
198            KeyStore trusted = getKeystore();
199            trusted.store(
200                    this.master.openFileOutput(DirectKeyChain.keyStoreFilename, Context.MODE_PRIVATE),
201                    password.toCharArray());
202            DirectKeyChain.password = password;
203        } catch (Exception e) {
204            FsUtils.checkOutOfSpace(e, false);
205            throw new KeystoreException(e);
206        }
207    }
208
209    private KeyStore newKeystore()
210    throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
211
212        DirectKeyChain.keystore = KeyStore.getInstance(DirectKeyChain.keyStoreType);
213        DirectKeyChain.keystore.load(null);
214        return DirectKeyChain.keystore;
215    }
216
217    private KeyStore getKeystore()
218    throws KeystoreException {
219
220        return getKeystore(DirectKeyChain.password);
221    }
222
223    private KeyStore getKeystore(String password)
224    throws KeystoreException {
225
226        if (DirectKeyChain.keystore == null) {
227            try {
228                if (keystoreExists()) {
229                    DirectKeyChain.keystore = KeyStore.getInstance(DirectKeyChain.keyStoreType);
230                    DirectKeyChain.keystore.load(this.master.openFileInput(
231                            DirectKeyChain.keyStoreFilename), password.toCharArray());
232                } else {
233                    newKeystore();
234                }
235                DirectKeyChain.password = password;
236            } catch (Exception e) {
237                                DirectKeyChain.password=null;
238                                DirectKeyChain.keystore=null;
239                if (IncorrectPasswordException.checkException(e)) {
240                   
241                    throw new IncorrectPasswordException(e);
242                }
243                throw new KeystoreException(e);
244            }
245        }
246       
247        return DirectKeyChain.keystore;
248    }
249   
250    private KeyStore reloadKeyStore(){
251        //TODO
252        if (DirectKeyChain.keystore!=null && DirectKeyChain.password!=null){
253                try {
254                                DirectKeyChain.keystore = KeyStore.getInstance(DirectKeyChain.keyStoreType);
255                                DirectKeyChain.keystore.load(this.master.openFileInput(
256                DirectKeyChain.keyStoreFilename), password.toCharArray());
257                } catch (KeyStoreException e) {}
258                  catch (CertificateException e) {}
259                          catch (FileNotFoundException e) {} 
260                  catch (NoSuchAlgorithmException e) {}
261                  catch (IOException e) {}             
262               
263               
264        }
265        else{}
266        return DirectKeyChain.keystore;
267
268    }
269   
270
271    private boolean keystoreExists() {
272
273        return this.master.getFileStreamPath(DirectKeyChain.keyStoreFilename).exists();
274    }
275
276    private void checkKeystoreOpen() throws KeystoreException {
277        if (DirectKeyChain.keystore == null) {
278            throw new KeystoreException("Neeed to open the keystore first");
279        }
280    }
281
282    public void createKeystoreAndChoosePrivateKeyAlias() {
283        final PasswordConfirmationDialog dialog =
284                new PasswordConfirmationDialog(this.master, R.string.keystore_create_password);
285        dialog.setAcceptListener(new DirectKeyChainAcceptListener(dialog, this.master));
286
287        dialog.show();
288    }
289   
290    private void openKeystoreAndChoosePrivateKeyAlias() {
291
292        final PasswordDialog dialog =
293                new PasswordDialog(this.master, R.string.keystore_password, true);
294        dialog.setAcceptListener(new DirectKeyChainOpenListener(dialog, this.master));
295        dialog.setRecreateListener(new DialogInterface.OnClickListener() {
296
297            @Override
298            public void onClick(DialogInterface dialog, int which) {
299                createKeystoreAndChoosePrivateKeyAlias();
300            }
301        });
302        dialog.show();
303    }
304   
305   
306   
307    private void startKeyChainActivityAndChoosePrivateKeyAlias() {
308       
309
310        if (DirectKeyChain.password==null)
311                this.choosePrivateKeyAlias();       
312            DirectKeyChain.this.buttonsKeyStoreStatus = true;
313           
314                DirectKeyChain.this.refreshAdapter();
315        /*Intent intent = new Intent(this.master, KeyChainActivity.class);
316        this.master.startActivityForResult(intent, ActivityResult.PRIVATE_KEY_ALIAS);*/
317    }
318
319   
320   
321    public ListView getListView() {
322                return listView;
323        }
324
325        public void setListView(ListView listView) {
326                this.listView = listView;
327        }
328
329        public void refreshAdapter(){
330                       
331               
332                try {
333                        this.reloadKeyStore();
334                                this.adapter = new DirectCertificateAdapter(DirectKeyChain.this, this.master);
335                                this.getListView().setAdapter(DirectKeyChain.this.adapter);
336
337                        } catch (KeystoreException e) {
338                                //DirectKeyChain.password=null;
339                                //DirectKeyChain.keystore=null;
340                        }
341               
342                       
343        }
344
345
346        public class DirectKeyChainAcceptListener implements View.OnClickListener {
347       
348                private PasswordConfirmationDialog dialog;
349                private Context context;
350
351                public DirectKeyChainAcceptListener(PasswordConfirmationDialog dialog, Context context){
352                        this.dialog=dialog;
353                        this.context=context;
354                }
355
356        @Override
357        public void onClick(View v) {
358            String newPassword = dialog.getPassword();
359            dialog.dismiss();
360            try {
361   
362                DirectKeyChain.this.newKeystore();
363                DirectKeyChain.this.saveKeystore(newPassword);
364                DirectKeyChain.this.startKeyChainActivityAndChoosePrivateKeyAlias();
365
366                /******************** OJO********************/
367                // En este punto se muestran los elementos dentro del keystore
368                /*********************************************/
369                Log.i("DEBUG", "Mostrar elementos1");
370               
371               
372//              if (DirectKeyChain.this.mainbar!=null)
373//                        DirectKeyChain.this.mainbar.prepareDisplayedChild(1);
374            } catch (OutOfSpaceError e) {
375                Toast.makeText(DirectKeyChain.this.master, R.string.error_no_space, Toast.LENGTH_LONG).show();
376            } catch (Exception e) {
377                Toast.makeText(DirectKeyChain.this.master, R.string.error_unknown, Toast.LENGTH_LONG).show();
378               // throw new RuntimeException(e);
379            } 
380           
381            /*try {
382                                DirectKeyChain.this.getListView().setAdapter(new DirectCertificateAdapter(DirectKeyChain.this, this.context));
383                        } catch (KeystoreException e) {
384
385                        }*/
386            DirectKeyChain.this.refreshAdapter();
387        }
388    }
389   
390       
391        public class DirectKeyChainOpenListener implements View.OnClickListener {
392       
393                private PasswordDialog dialog;
394                private Context context;
395
396                public DirectKeyChainOpenListener(PasswordDialog dialog, Context context){
397                        this.dialog=dialog;
398                        this.context=context;
399                }
400               
401            @Override
402            public void onClick(View v) {
403                String password = dialog.getPassword();
404                boolean ok = false;
405                try {
406                    getKeystore(password);
407                    ok = true;
408                } catch (IncorrectPasswordException e) {
409                    ok = false;
410                                DirectKeyChain.password=null;
411                                //DirectKeyChain.keystore=null;
412                               
413                    dialog.retry();
414                } catch (KeystoreException e) {
415                    //throw new RuntimeException(e);
416                                DirectKeyChain.password=null;
417                                DirectKeyChain.keystore=null;
418                }
419                if (ok) {
420                        DirectKeyChain.this.buttonsKeyStoreStatus = true;
421                        Log.i("DEBUG", "Mostrar elementos2");
422                    dialog.dismiss();
423                    startKeyChainActivityAndChoosePrivateKeyAlias();
424                }
425               
426               
427               
428                /*try {
429                        if (DirectKeyChain.this.adapter==null){
430                                DirectKeyChain.this.adapter = new DirectCertificateAdapter(DirectKeyChain.this, this.context);
431                                        DirectKeyChain.this.getListView().setAdapter(DirectKeyChain.this.adapter);
432                        }
433                        else{
434                                DirectKeyChain.this.adapter.notifyDataSetChanged();
435                        }
436                        } catch (KeystoreException e) {
437
438                        }*/
439                DirectKeyChain.this.refreshAdapter();
440               
441            }
442        }
443       
444   
445    private static class PrivateKeyEnumeration implements Enumeration<String> {
446
447        private KeyStore keystore;
448        private Enumeration<String> aliases;
449        private String next;
450
451        public PrivateKeyEnumeration(KeyStore keystore) throws KeyStoreException {
452
453            this.keystore = keystore;
454            this.aliases = keystore.aliases();
455            this.next = lookForNextPrivateKeyAlias();
456        }
457
458        private String lookForNextPrivateKeyAlias() throws KeyStoreException {
459
460            while (this.aliases.hasMoreElements()) {
461                String alias = this.aliases.nextElement();
462                if (this.keystore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
463                    return alias;
464                }
465            }
466            return null;
467        }
468
469        @Override
470        public boolean hasMoreElements() {
471
472            return this.next != null;
473        }
474
475        @Override
476        public String nextElement() {
477
478            String element = this.next;
479            try {
480                this.next = lookForNextPrivateKeyAlias();
481            } catch (KeyStoreException e) {
482                //throw new RuntimeException(e);
483            }
484            return element;
485        }
486    }
487
488
489        public boolean isPasswordCorrect() {
490                return (DirectKeyChain.password!=null);
491        }   
492}
Note: See TracBrowser for help on using the repository browser.