2013-08-20 2 views
3

Я разрабатываю корпоративное Android-приложение, поэтому необходимо создать безопасное соединение между клиентом (эмулятор/тестовый телефон Android) и сервером во время моего хотя сертификат сервера самоподписан, в то время как законный сертификат покупается компанией (что-то вне моего контроля пока).Использование самозаверяющего сертификата для создания безопасного соединения клиент-сервер в android

Мне нужно доверять самозаверяющему сертификату сервера и его сертификату, который, естественно, не заслуживает поддержки ОС Android. Я следую google's suggestion for creating an HTTPS environment in this scenario почти дословно.

Проблема я в настоящее время сталкивается в том, что я не могу получить доступ к .crt файл, как в этой строке из примера Google:

InputStream caInput = new BufferedInputStream(
    new FileInputStream("load-der.crt")); 

На месте выше, я использую:

InputStream caInput = new BufferedInputStream(
getResources().openRawResource(R.raw.mycrtfile)); 

, чтобы открыть InputStream, полученный от mycrtfile.crt, где .crt файл существует в /res/raw/mycrtfile.crt. Тем не менее, я получаю NullPointerException на этой строке.

Есть ли лучший способ сохранить и получить доступ к файлу сертификата, который мне нужно загрузить как InputStream или FileInputStream, чем как необработанный ресурс, хранящийся в каталоге res?

+0

У меня была такая же проблема, чтобы проверить мой ответ, и если вы смущены на шагах, я могу вам помочь. Это будет принимать только ваш сертификат. – Moy

+0

Спасибо @Moises, я закончил работу над этим проектом в течение дня, поэтому завтра я рассмотрю решение и дам вам знать, застрял ли я. – ironicaldiction

ответ

7

Существуют несколько способов решить вашу проблему, но вот один я использую: Всех шагов в этой ссылке http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/, но некоторые части могут быть спутаны, так что я объясню весь процесс:

1.- Храните свой файл mycrtfile.crt в пути к знанию, я скажу c: BKS/mycrtfile.crt.

2.-Чтобы создать свой BKS или магазин ключей, вам понадобится файл bcprov-jdk15on-146.jar, этот класс будет выполнять всю работу для нас, есть разные версии, но этот работает для меня http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar также хранить этот файл в C: BKS/

3.-Теперь вы будете использовать Keytool (keytool поставляется с Java SDK. Вы должны найти его в каталоге, который содержит javac), чтобы сгенерировать наше хранилище ключей и убедиться, что он работает перейдите в свой cmd и введите «Keytool», вы увидите доступные команды, которые, значит, работают, или вы можете получить доступ к «C: \ Program Files (x86) \ Java \ jre7 \ bin> keytool».

4.-Теперь, когда все находится в месте, мы можем создать хранилище ключей с этой командной строки:

Keytool -importcert -v -trustcacerts -file "C: \ BKS/mycrtfile.crt" -alias сертификат - Хранилище ключей "C: \ BKS/keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "C: \ BKS/пров-jdk15on-146.jar" -storetype BKS -storepass MySecret

Давайте посмотрим что в этой строке (я действительно был смущен в этой части): - «c: \ BKS/mycrtfile.crt»: это путь к вашему сертификату. - «c: \ BKS/keystore.bks» - это путь, по которому мы будем хранить хранилище ключей, и вы можете изменить имя out-put, которое я использую keystore, просто убедитесь, что файл расширения .bks - «c: \ BKS/prov-jdk15on-146.jar ": это путь к нашему файлу, который будет выполнять всю работу. -mysecret: это пароль для использования хранилища ключей, который вам понадобится для этого пароля, поэтому не забывайте об этом.

Редакцией:
4.1- использовать Также эту командную строку для проверки, если сертификат был импортирован правильно в хранилище ключей:

Keytool -list -keystore "Рез/сырье/Keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "C: \ BKS/пров-jdk15on-146.jar" -storetype BKS -storepass MySecret

4,2 -н После этого вы должны увидеть выход, как это:

RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24: 77: D9: A8: 91: D1: 3B: FA: 88: 2D: C2: FF: F8: CD: 33: 93 IntermediateCA, 22.10. 2010, trustedCertEntry, Thumbprint (MD5): 98: 0F: C3: F8: 39: F7: D8: 05: 07: 02: 0D: E3: 14: 5B: 29: 43
Это означает, что он был импортирован правильно.

5.- После этого, если вы заходите в свою папку BKS, вы получите файл Keystore.bks, который означает, что мы в пути.

6.- Теперь перейдите к части ANDROID. В вашем проекте проверьте, есть ли у вас «необработанная» папка, которая должна быть в вашем проекте/res/raw, если не создайте эту папку под res.

7. скопируйте файл Keystore.bks в папку raw. Все на месте теперь позволяет перейти к коду.

8 .--- Теперь мы создадим класс, чтобы читать и доверять нашему: хранилища ключей

import java.io.InputStream; 
import java.security.KeyStore; 
import org.apache.http.conn.ClientConnectionManager; 
import org.apache.http.conn.scheme.PlainSocketFactory; 
import org.apache.http.conn.scheme.Scheme; 
import org.apache.http.conn.scheme.SchemeRegistry; 
import org.apache.http.conn.ssl.SSLSocketFactory; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.impl.conn.SingleClientConnManager; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 

import com.futureconcepts.anonymous.R; 
import android.content.Context; 


public class Client extends DefaultHttpClient { 
final Context context; 
    public Client(Context context) { 
     this.context = context; 
    } 

    @Override 
    protected ClientConnectionManager createClientConnectionManager() { 
     SchemeRegistry registry = new SchemeRegistry(); 
     registry.register(new Scheme("http", 
     PlainSocketFactory.getSocketFactory(), 80)); 
     // Register for port 443 our SSLSocketFactory with our keystore 
     // to the ConnectionManager 
     registry.register(new Scheme("https", newSslSocketFactory(),443)); 

    HttpParams httpParams = new BasicHttpParams(); 
    HttpConnectionParams.setConnectionTimeout(httpParams,9000); 
    HttpConnectionParams.setSoTimeout(httpParams, 9000); 

     return new SingleClientConnManager(httpParams, registry); 
    } 


    private SSLSocketFactory newSslSocketFactory() { 
     try { 

      // Get an instance of the Bouncy Castle KeyStore format 
      KeyStore trusted = KeyStore.getInstance("BKS");//put BKS literal 
      // Get the raw resource, which contains the keystore with 
      // your trusted certificates (root and any intermediate certs) 
      InputStream in =context.getResources().openRawResource(R.raw.keystore); 
      try { 
       // Initialize the keystore with the provided trusted certificates 
       // Also provide the password of the keystore 
       trusted.load(in, "mysecret".toCharArray()); 
      } finally { 
       in.close(); 
      } 
      // Pass the keystore to the SSLSocketFactory. The factory is responsible 
      // for the verification of the server certificate. 
      SSLSocketFactory sf = new SSLSocketFactory(trusted); 
      // Hostname verification from certificate 

      sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); 
      return sf; 
     } catch (Exception e) { 
      throw new AssertionError(e); 
     } 
    } 

} 

9.And мы сделали сейчас, чтобы сделать запрос просто сделать это: HttpClient клиент = новый клиент (это); /// настройка вашего Httpclient.

Теперь вы доверяете только своему сертификату. Надеюсь, это объяснение поможет вам или кому-либо с той же проблемой.

+0

Сначала у меня были проблемы с вышеуказанной ссылкой. Я смог быстро найти решение [this] (http://paxbat-android.blogspot.com/2013/05/android-https-and-not-trusted-server.html) для настройки HTTPS в моем приложении. Мое беспокойство, однако, заключается в том, что это просто отключает все проверки SSL, и какая-то вредоносная сторонняя сторона может внедрить свой собственный сторонний сертификат. – ironicaldiction

+0

Я не думаю, что это хорошая идея, просто отключите проверку для самоподписанных сертификатов. Лучшее, что вы можете сделать, это доверять только вашему сертификату, если для этого у вас есть некоторая безопасность после создания запроса, иначе вы можете принять все сертификаты (которые я считаю очень плохими, но это можно сделать). Ссылка, которую я вам дам, поможет вам создать хранилище ключей для вашего сертификата, и вы будете доверять только этому сертификату, я объясню, что весь процесс просто даст мне некоторое время. Это кажется сложным, но это не так, и это правильный способ сделать это. – Moy

+0

Большое спасибо за более подробное объяснение. Я смотрю дальше. – ironicaldiction

0

Keystore (Здесь отличный article на Keystore и связанные с ним проблемы) и KeyChain сделать трюк, но вам может потребоваться проверить уровень API, на который вы нацеливаете. Кроме того, поскольку вы упомянули Enterprise Application, вам может потребоваться рассмотреть вопрос о присвоении сертификата. This поможет вам получить сертификат.

0

1) Создание каталога "активов" в приложение/SRC/основные/

2) Поместите свой сертификат в этом каталоге.

3) Теперь вы можете получить InputStream:

InputStream is = this.getAssets().open("mycrtfile.crt"); 

Чтобы использовать this.getAssets() вы должны быть в деятельности, потому что в деятельности «это» соответствуют «контексту». Если вы не находитесь в действии, вы должны передать контекст (это) в качестве аргумента.

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