source: dispositivos_moviles/TibisayMovil/src/ve/gob/cenditel/tibisaymovil/DirectKeyChain.java @ 8379cd8

Last change on this file since 8379cd8 was 8379cd8, checked in by Antonio Araujo Brett <aaraujo@…>, 11 years ago

Agregado encabezado de licencia a archivos fuentes.

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