2011-02-09 1 views
17

I my app Я хочу использовать https-соединение с указанным пользователем сервером, который использует самозаверяющий сертификат. То, что я собрал уже есть, чтоКак программно добавить сертификаты в доверительный магазин и использовать это также для проверки подлинности сервера

  • самостоятельно подписанные сертификаты отвергнута (как и ожидалось)
  • андроид хранилище ключей/доверенное хранилище не используется для приложений, поэтому приложения должны создавать и использовать свои собственные доверенных сертификатов,
  • есть «Keytool» в JDK для создания доверенных сертификатов, которые могут быть поставлены в приложение в качестве ресурса, который, однако, не является решением, так как я не знаю, сервер (и его сертификат заранее)

с https-сервер указан пользователем, я не знаю сертификата сервера befo и, следовательно, хотите добавить сертификат сервера программно в доверенное хранилище приложения (показывая сертификат пользователю и попросите его принять его). После добавления в доверительный магазин приложение должно использовать этот доверенный сервер для аутентификации сервера.

Я НЕ хочу просто принимать каждый самоподписанный сертификат без проверки пользователем отпечатка пальца, как предлагают некоторые примеры в Интернете.

Теперь проблема в том, что я совершенно не знаком с Java и Android, и я стараюсь понять внутреннюю работу AndroidHttpClient или DefaultHttpClient. У меня есть базовый HTTP, работающий в моем приложении, но не нашел никакого примера о том, как на самом деле ADD-сертификаты доверять в приложении по запросу по запросу пользователя.

Кто-нибудь знает, как достичь этого или знает рабочий пример, на который я могу смотреть?

Любые советы приветствуются. Благодарю.

EDIT: найдено решение в TrustManagerFactory.java class of K9 Mail. Я предлагаю взглянуть на него, если у вас есть тот же вопрос.

+2

Я знаю, что это старый вопрос, но это именно то, что я ищу. Вы нашли решение? – nikmin

+0

Вы нашли решение для этого @nikmin –

+0

@machtnix: Как вы его достигли, используя класс TrustManagerFactory для почты k9. как вы упомянули. Не могли бы вы мне помочь ? –

ответ

-1

Вы можете использовать самоподписанные сертификаты. Чтобы использовать самозаверяющий сертификат, вы можете преобразовать его в keystore в стиле bouncy lock, который поддерживается Android, а затем сохранить его в качестве исходного ресурса в вашем проекте приложений Android. Как конвертировать и использовать его, все детали можно найти в блоге Боба. Вот ссылка на то же самое - http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html. Это работало довольно хорошо. Надеюсь, это поможет

+5

Я могу только предположить, что вы не прочитали вопрос, в частности, бит, в котором говорится: «Поскольку https-сервер указан пользователем, я заранее не знаю сертификат сервера и, следовательно, хочу программным образом добавить сертификат сервера в доверительный магазин приложения» – Fuzzy

8

Решение было найдено некоторое время назад, но никто не создал ответ еще, чтобы помочь другим, поэтому сегодня я буду Point Pimp (ette) и опубликую URL-адрес, добавленный в качестве решения, плюс копию в коде из общедоступного источника. Надеюсь, что это поможет другим людям решить проблему. :)


Here's the URL для кода ниже.

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

ссылка не активна больше – Bhargav

+1

@Bhargav thx для обновления.Хорошо, что мы скопировали код из него, прежде чем он исчез. – Lizz

Смежные вопросы