簡體   English   中英

使用自簽名證書在android中創建安全的客戶端 - 服務器連接

[英]Using a self-signed certificate to create a secure client-server connection in android

我正在開發一個企業Android應用程序,因此有必要在我的測試階段在客戶端(android模擬器/測試手機)和服務器之間創建一個安全的連接,即使服務器的證書是自簽名的,而正在購買合法的證書由公司(我現在控制的東西)。

我需要信任服務器的自簽名證書及其證書授權,當然,它本身不受Android操作系統的信任。 我正在遵循谷歌關於在這個場景中幾乎逐字創建HTTPS環境的建議

我目前面臨的問題是我無法訪問我的.crt文件,就像谷歌的例子一樣:

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

代替上述,我使用:

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

打開從mycrtfile.crt派生的InputStream ,其中.crt文件存在於/res/raw/mycrtfile.crt 但是,我在該行上得到NullPointerException

是否有更好的方法來存儲和訪問我需要作為InputStreamFileInputStream加載的cert文件,而不是存儲在res目錄中的原始資源?

有不同的方法來解決您的問題,但這是我使用的方法:所有步驟都在這個鏈接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 certificate -keystore“c:\\ BKS / keystore.bks”-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath“c: \\ BKS / prov-jdk15on-146.jar“-storetype BKS -storepass mysecret

讓我們看看這一行是什么(我在這一部分真的很困惑): - “c:\\ BKS / mycrtfile.crt”:這是你的證書的路徑。 - “c:\\ BKS / keystore.bks”這是我們存儲密鑰庫的路徑,您可以更改我使用密鑰庫的輸出名稱,只需確保擴展文件是.bks - “c:\\ BKS /prov-jdk15on-146.jar“:這是我們文件的路徑,可以完成所有工作。 -mysecret:這是使用密鑰庫的密碼,你需要這個密碼,所以不要忘記這一點。

編輯:
4.1-還可以使用此命令行來驗證證書是否已正確導入密鑰庫:

keytool -list -keystore“res / raw / Keystore.bks”-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath“c:\\ BKS / prov-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部分。 在你的項目中檢查你是否有“raw”文件夾,如果沒有在res下創建這個文件夾,它必須在你的項目/ res / raw中。

7.將Keystore.bks文件復制到raw文件夾中。 現在一切都准備就緒了。

8 .---現在我們將創建一個類來閱讀和信任我們的Keystore:

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.我們現在做了一個請求就是這樣做:HttpClient client = new Client(this); ///設置您的Httpclient。

就是現在你只相信你的證書了。 我希望這個解釋可以幫助您或任何有同樣問題的人。

Keystore (這是一篇關於Keystore和相關問題的精彩文章 )和KeyChain可以解決這個問題,但您可能需要檢查您所定位的API級別。 此外,由於您提到了Enterprise Application,因此您可能需要考慮證書固定。 有助於您獲得證書固定。

1)在app / src / main /中創建目錄“assets”

2)將證書放在此目錄中。

3)現在你可以得到InputStream:

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

要使用this.getAssets(),你必須在Activity中,因為在Activity中“this”對應於“Context”。 如果您不在Activity中,則必須將Context(this)作為參數傳遞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM