2011-02-09 16 views
17

I mia app Voglio utilizzare una connessione https a un server specificato dall'utente che utilizza un certificato autofirmato. Quello che ho raccolto da ora è, cheCome aggiungere i certificati a un truststore al livello di programmazione e utilizzarlo anche per verificare l'autenticazione del server

  • certificati self firmati sono rifiutati (come previsto)
  • l'androide keystore/truststore non viene utilizzato per le applicazioni, in modo da applicazioni hanno per costruire e utilizzare il proprio truststore,
  • c'è un "keytool" nel JDK di costruire un truststore che può essere fornito per l'applicazione come una risorsa, che però non è una soluzione in quanto non so il server (e il relativo certificato in anticipo)

dal il server https è specificato dall'utente, non conosco il befo del certificato del server rehand e quindi si desidera aggiungere il certificato del server a livello di programmazione al truststore dell'app (mostrando il certificato all'utente e chiedergli di accettarlo). Una volta aggiunto al truststore, l'app utilizza tale truststore per autenticare il server.

NON voglio semplicemente accettare tutti i certificati autofirmati senza che l'utente verifichi l'impronta digitale come suggeriscono alcuni esempi sul web.

Ora il problema è che sono completamente nuovo in Java e Android e sto lottando per capire il funzionamento interno di AndroidHttpClient o DefaultHttpClient. Ho un HTTP di base che funziona nella mia app, ma non ho trovato alcun esempio su come effettivamente AGGIUNGERE certificati su un truststore all'interno dell'app a richiesta dell'utente.

Qualcuno sa come raggiungerlo o conosce un esempio funzionante che posso guardare?

Eventuali suggerimenti sono apprezzati. Grazie.

MODIFICA: trovata la soluzione nello TrustManagerFactory.java class of K9 Mail. Suggerisco di dargli un'occhiata se stai facendo la stessa domanda.

+2

So che questa è una vecchia domanda, ma questo è proprio quello che sto cercando. Hai trovato una soluzione? – nikmin

+0

Hai trovato qualche soluzione a questo @nikmin –

+0

@machtnix: Come hai ottenuto utilizzando la classe TrustManagerFactory di k9 mail. come hai menzionato. Potete per favore aiutarmi ? –

risposta

-1

È possibile utilizzare certificati autofirmati. Per utilizzare un certificato autofirmato, è possibile convertirlo in un keystore bouncy castle format supportato da Android e quindi memorizzarlo come risorsa non elaborata nel progetto dell'app Android. Come convertirlo e usarlo, tutti i dettagli possono essere trovati sul blog di Bob. Ecco il link per lo stesso - http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html. Questo ha funzionato abbastanza bene. Spero che questo aiuti

+5

Posso solo presumere che tu non abbia letto la domanda, in particolare il bit che dice "Poiché il server https è specificato dall'utente, non conosco il certificato del server in anticipo e quindi voglio aggiungere il certificato del server al truststore dell'app" – Fuzzy

8

La soluzione è stata trovata qualche tempo fa, ma nessuno ha ancora creato la risposta per aiutare gli altri, quindi questa mattina sarò il Point Pimp (ette) e inserirò l'URL aggiunto come soluzione, più una copia nel codice dalla fonte pubblica. Spero che questo aiuti gli altri a guidare la soluzione. :)


Here's the URL per il codice di seguito.

package com.fsck.k9.mail.store; 

import android.app.Application; 
import android.content.Context; 
import android.util.Log; 
import com.fsck.k9.K9; 
import com.fsck.k9.helper.DomainNameChecker; 
import org.apache.commons.io.IOUtils; 

import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import java.util.HashMap; 
import java.util.Map; 

public final class TrustManagerFactory { 
    private static final String LOG_TAG = "TrustManagerFactory"; 

    private static X509TrustManager defaultTrustManager; 
    private static X509TrustManager unsecureTrustManager; 
    private static X509TrustManager localTrustManager; 

    private static X509Certificate[] lastCertChain = null; 

    private static File keyStoreFile; 
    private static KeyStore keyStore; 


    private static class SimpleX509TrustManager implements X509TrustManager { 
     public void checkClientTrusted(X509Certificate[] chain, String authType) 
     throws CertificateException { 
     } 

     public void checkServerTrusted(X509Certificate[] chain, String authType) 
     throws CertificateException { 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 
    } 

    private static class SecureX509TrustManager implements X509TrustManager { 
     private static final Map<String, SecureX509TrustManager> mTrustManager = 
      new HashMap<String, SecureX509TrustManager>(); 

     private final String mHost; 

     private SecureX509TrustManager(String host) { 
      mHost = host; 
     } 

     public synchronized static X509TrustManager getInstance(String host) { 
      SecureX509TrustManager trustManager; 
      if (mTrustManager.containsKey(host)) { 
       trustManager = mTrustManager.get(host); 
      } else { 
       trustManager = new SecureX509TrustManager(host); 
       mTrustManager.put(host, trustManager); 
      } 

      return trustManager; 
     } 

     public void checkClientTrusted(X509Certificate[] chain, String authType) 
     throws CertificateException { 
      defaultTrustManager.checkClientTrusted(chain, authType); 
     } 

     public void checkServerTrusted(X509Certificate[] chain, String authType) 
     throws CertificateException { 
      // FIXME: Using a static field to store the certificate chain is a bad idea. Instead 
      // create a CertificateException subclass and store the chain there. 
      TrustManagerFactory.setLastCertChain(chain); 
      try { 
       defaultTrustManager.checkServerTrusted(chain, authType); 
      } catch (CertificateException e) { 
       localTrustManager.checkServerTrusted(new X509Certificate[] {chain[0]}, authType); 
      } 
      if (!DomainNameChecker.match(chain[0], mHost)) { 
       try { 
        String dn = chain[0].getSubjectDN().toString(); 
        if ((dn != null) && (dn.equalsIgnoreCase(keyStore.getCertificateAlias(chain[0])))) { 
         return; 
        } 
       } catch (KeyStoreException e) { 
        throw new CertificateException("Certificate cannot be verified; KeyStore Exception: " + e); 
       } 
       throw new CertificateException("Certificate domain name does not match " 
               + mHost); 
      } 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      return defaultTrustManager.getAcceptedIssuers(); 
     } 

    } 

    static { 
     java.io.InputStream fis = null; 
     try { 
      javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509"); 
      Application app = K9.app; 
      keyStoreFile = new File(app.getDir("KeyStore", Context.MODE_PRIVATE) + File.separator + "KeyStore.bks"); 
      keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
      try { 
       fis = new java.io.FileInputStream(keyStoreFile); 
      } catch (FileNotFoundException e1) { 
       fis = null; 
      } 
      try { 
       keyStore.load(fis, "".toCharArray()); 
      } catch (IOException e) { 
       Log.e(LOG_TAG, "KeyStore IOException while initializing TrustManagerFactory ", e); 
       keyStore = null; 
      } catch (CertificateException e) { 
       Log.e(LOG_TAG, "KeyStore CertificateException while initializing TrustManagerFactory ", e); 
       keyStore = null; 
      } 
      tmf.init(keyStore); 
      TrustManager[] tms = tmf.getTrustManagers(); 
      if (tms != null) { 
       for (TrustManager tm : tms) { 
        if (tm instanceof X509TrustManager) { 
         localTrustManager = (X509TrustManager)tm; 
         break; 
        } 
       } 
      } 
      tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509"); 
      tmf.init((KeyStore)null); 
      tms = tmf.getTrustManagers(); 
      if (tms != null) { 
       for (TrustManager tm : tms) { 
        if (tm instanceof X509TrustManager) { 
         defaultTrustManager = (X509TrustManager) tm; 
         break; 
        } 
       } 
      } 

     } catch (NoSuchAlgorithmException e) { 
      Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e); 
     } catch (KeyStoreException e) { 
      Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e); 
     } finally { 
      IOUtils.closeQuietly(fis); 
     } 
     unsecureTrustManager = new SimpleX509TrustManager(); 
    } 

    private TrustManagerFactory() { 
    } 

    public static X509TrustManager get(String host, boolean secure) { 
     return secure ? SecureX509TrustManager.getInstance(host) : 
       unsecureTrustManager; 
    } 

    public static KeyStore getKeyStore() { 
     return keyStore; 
    } 

    public static void setLastCertChain(X509Certificate[] chain) { 
     lastCertChain = chain; 
    } 
    public static X509Certificate[] getLastCertChain() { 
     return lastCertChain; 
    } 

    public static void addCertificateChain(String alias, X509Certificate[] chain) throws CertificateException { 
     try { 
      javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509"); 
      for (X509Certificate element : chain) { 
       keyStore.setCertificateEntry 
       (element.getSubjectDN().toString(), element); 
      } 

      tmf.init(keyStore); 
      TrustManager[] tms = tmf.getTrustManagers(); 
      if (tms != null) { 
       for (TrustManager tm : tms) { 
        if (tm instanceof X509TrustManager) { 
         localTrustManager = (X509TrustManager) tm; 
         break; 
        } 
       } 
      } 
      java.io.OutputStream keyStoreStream = null; 
      try { 
       keyStoreStream = new java.io.FileOutputStream(keyStoreFile); 
       keyStore.store(keyStoreStream, "".toCharArray()); 
      } catch (FileNotFoundException e) { 
       throw new CertificateException("Unable to write KeyStore: " + e.getMessage()); 
      } catch (CertificateException e) { 
       throw new CertificateException("Unable to write KeyStore: " + e.getMessage()); 
      } catch (IOException e) { 
       throw new CertificateException("Unable to write KeyStore: " + e.getMessage()); 
      } finally { 
       IOUtils.closeQuietly(keyStoreStream); 
      } 

     } catch (NoSuchAlgorithmException e) { 
      Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e); 
     } catch (KeyStoreException e) { 
      Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e); 
     } 
    } 
} 
+1

il collegamento non è più attivo – Bhargav

+1

@Bhargav thx per l'aggiornamento.Per fortuna abbiamo copiato il codice da esso prima che scomparisse. – Lizz

Problemi correlati