2012-06-01 37 views
4

這件事一直在困擾我幾天。我讀過關於整個問題的很多其他問題,但仍然無法繼續。如何在Android中使用自簽名SSL證書

我已經創建了一個簡單的測試應用程序來測試Android上的SSL。應用程序只有一個按鈕,當點擊時,應用程序會嘗試通過SSL加密連接向我的測試服務器發送「Hello World」,然後使用完全相同的短語進行響應。

首先,我使用openssl爲我的服務器創建了一個測試密鑰和測試證書。然後我一直遵循Crazy Bob's blog中顯示的說明。我從Bouncy Castle的網站直接獲得了Bouncy Castle提供商,創建了一個可信的密鑰庫,如Crazy Bob的博客所示,並且我相信這一切都正確。

當我試圖運行我的代碼時,出現異常「IOException:密鑰存儲區的版本錯誤」。然後我在StackOverflow上找到了this question。在那裏有人建議我應該嘗試使用舊的充氣城堡供應商,而不是最新的bcprov-jdk15on-147.jar。我繼續記住這一點,並最終嘗試了從jdk13-146到jdk16-146的每個bcprovider。每次我仍然得到相同的「IOExcpetion:密鑰存儲的錯誤版本」。例外。

然後我發現yet another question關於StackOverflow上的類似問題。有人設法通過使用512位大小的密鑰而不是1024大小的密鑰來擺脫該異常。好吧,我試了一下,什麼都沒做,但同樣的例外。

所以我現在在這裏,想知道下一步該做什麼。我幾乎沒有想法和谷歌搜索結果。

我的網頁代碼是瘋狂鮑勃代碼的1對1副本,此外,應用程序只有處理按鈕的活動類。我試圖在API級別7上實現這一點。

任何幫助將不勝感激。謝謝。

+0

如果您將目標API移動到類似10或14的東西,它是否會開始工作?在處理較舊的API級別時,測試較新的API並不是一個壞主意,只是爲了確保它不是兼容性問題。 – matt5784

+0

我需要爲大腦樹的Android項目創建「.pem」文件。我安裝了openssl並運行以下命令:openssl> s_client -connect $ https://xxx.xxx.xx:443 2>&1 | \ sed -ne'/ -BEGIN CERTIFICATE - /,/ - END CERTIFICATE-/p'> mycert.pem 但我在s_client中出錯。請幫幫我。我從Crazy Bob的博客得到命令。 –

回答

0

當我試圖向EWS請求時,它與my question類似。你可以參考this link並下載example source code然後修改它就像我的答案。希望這可以幫助!

更新
以下命令爲我工作(我嘗試了大約2個月前):

C:\OpenSSL-Win32\bin>keytool -importcert -v -trustcacerts -file "d:/cer.cer" 
    -alias parkgroup_restful -keystore "D:/parkgroup-ws-client.bks" 
    -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath 
"D:/bcprov-jdk16-145.jar" -storetype BKS -storepass 1234567 

    .... /**It should show the result here**/ 

    Trust this certificate? [no]: yes 
    Certificate was added to keystore 
    [Storing D:/parkgroup-ws-client.bks] 

    C:\OpenSSL-Win32\bin>keytool -list -keystore "D:/parkgroup-ws-client.bks" -provi 
    der org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "D:/bcprov- 
    jdk16-145.jar" -storetype BKS -storepass 1234567 

    Keystore type: BKS 
    Keystore provider: BC 

    Your keystore contains 1 entry 

    parkgroup_restful, Apr 10, 2012, trustedCertEntry, 
    Certificate fingerprint (MD5): 36:47:88:62:23:1C:F3:52:17:BE:7A:A9:94:56:19:18 

你可以看到,我用bcprov-jdk16-145.jar和OpenSSL庫。你可以嘗試一下。
另一種工具來創建密鑰庫:http://portecle.sourceforge.net/

+0

感謝您的鏈接,但仍無法克服「密鑰存儲區的錯誤版本」異常。 – zaplec

+0

@zaplec:我已經更新了我的答案 – R4j

+0

我不確定我是否真的明白了你在第一行所做的事情,因爲在我看來,你從未使用過在此創建的PEM。你能解釋一下嗎?否則,你的解決方案看起來很像我試過的。我試過bcprov-jdk16-145.jar(加上其他版本)和openssl。 – zaplec

2

2個選擇:

  1. 你可以做你做什麼,並創建自己的密鑰存儲和我已經做了,這裏是從我的代碼指令我存儲(因爲它是如此耗費時間得到它的工作):

    要生成PKS:

    1. 在IIS7然後EXP創建證書orted作爲pfx。遵循SelfSSL的指示:http://www.robbagby.com/iis/self-signed-certificates-on-iis-7-the-easy-way-and-the-most-effective-way/ 1a。下載工具:http://cid-3c8d41bb553e84f5.skydrive.live.com/browse.aspx/SelfSSL 1b。運行:SelfSSL/N:CN = mydomainname/V:1000/S:1/P:8081 我在我的服務器 1c上使用端口8181。從IIS管理器導出到cert.pfx
    2. 運行命令行中的SSL,以文件轉換成X.509: OpenSSL的PKCS12 -in C:\ cert.pfx退房手續C:\ cert.cer -nodes
    3. 編輯文件並刪除所有除了----- BEGIN .... END CERTIFICATE -----重要!它正在工作,當我得到適當的(5)破折號並將標籤和數據放在不同的行上時
    4. 使用keytool。 C:\ Java \ JDK \ bcprov.jar單獨下載 C:\ Users> keytool -import -v -trustcacerts -alias key_alias -file C:\ cert.cer -keystore C:\ mystore.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath C:\ Java的\ JDK \ bcprov.jar -storepass 123456
  2. 建立信任所有密鑰庫和忘掉這一切。基本上,您可以使用任何SSL而不出錯。如果你真的關心,只需在生產中禁用它。下面是代碼,我用它來獲取SSL客戶端準備(假設你使用Apache HTTP客戶端)

    private HttpClient getHttpClient() 
    { 
        HttpParams params = new BasicHttpParams(); 
    
        //Set main protocol parameters 
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
        HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); 
        HttpProtocolParams.setUseExpectContinue(params, true); 
    
        // Turn off stale checking. Our connections break all the time anyway, and it's not worth it to pay the penalty of checking every time. 
        HttpConnectionParams.setStaleCheckingEnabled(params, false); 
        // FIX v2.2.1+ - Set timeout to 30 seconds, seems like 5 seconds was not enough for good communication 
        HttpConnectionParams.setConnectionTimeout(params, 30 * 1000); 
        HttpConnectionParams.setSoTimeout(params, 30 * 1000); 
        HttpConnectionParams.setSocketBufferSize(params, 8192); 
    
        // Don't handle redirects -- return them to the caller. Our code often wants to re-POST after a redirect, which we must do ourselves. 
        HttpClientParams.setRedirecting(params, false); 
    
        // Register our own "trust-all" SSL scheme 
        SchemeRegistry schReg = new SchemeRegistry(); 
        try 
        { 
         KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
         trustStore.load(null, null); 
    
         TrustAllSSLSocketFactory sslSocketFactory = new TrustAllSSLSocketFactory(trustStore); 
         sslSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
    
         Scheme sslTrustAllScheme = new Scheme("https", sslSocketFactory, 443); 
         schReg.register(sslTrustAllScheme); 
        } 
        catch (Exception ex) 
        { 
         LogData.e(LOG_TAG, ex, LogData.Priority.None); 
        } 
    
        ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg); 
        return new DefaultHttpClient(conMgr, params); 
    } 
    
+0

如果我使用TRUST ALL選項,是否意味着我的應用程序是唯一一個信任所有網站的應用程序?換句話說,我只是想確保它不會以任何方式影響手機上的其他應用程序。我的應用程序使用的URL是硬編碼的,因爲它永遠不會更改,因此允許應用程序信任所有站點可能是安全的,因爲它永遠不會嘗試連接到某個「不受信任」的站點。 – zaplec

+0

是的,您只會將其設置爲信任此特定連接的所有證書。其他應用程序不會受到影響 – katit

+0

此信任所有解決方案的工作原理,但它可能使應用程序仍然容易受到中間人攻擊。出於測試目的,這是可以的,但我認爲我需要繼續爭取讓SSL工作只有一個受信任的站點:) – zaplec

0

嗯,我也面臨這個同樣的情況,並解決它,我花了幫助,從相同的博客文章(http://nelenkov.blogspot.in/2011/12/using-custom-certificate-trust-store-on.html)簡稱通過R4j。以下是相關的步驟:

  1. 創建自定義trustore:我用Portecle創建從我的服務器密鑰庫和進口的公鑰證書進去。
  2. 創建密鑰對定製密鑰庫:密鑰工具-genkeypair -alias樣品-keyalg RSA -sigalg SHA1withRSA -dname「CN =戒靈,OU =攻擊,O =索倫企業,L =魔多,ST =中間地球,C = ME「-keypass welcome123 -validity 365 -storetype pkcs12 -keystore g:\ mordor_key_store.pfx -storepass welcome123 -keyize 2048
  3. 然後,您使用它們,如nelkov的博客中所述。您可能還需要創建自己的自定義AbstractVerifier的情況下,你的土地到那裏證書爲abc.com頒發的形勢和驗證拒絕www.abc.com
  4. 最後創建安全了HTTPClient,你可以這樣做這樣的:

     public static DefaultHttpClient getSecureHttpClient(){ 
        SchemeRegistry schemeRegistry = new SchemeRegistry(); 
        SSLContext sslContext = null; 
        try { 
         sslContext = createSslContext(true); 
        } catch (GeneralSecurityException e) { 
         e.printStackTrace(); 
        } 
        final X509HostnameVerifier delegate = new BrowserCompatHostnameVerifier(); 
        MySSLSocketFactory socketFactory = new MySSLSocketFactory(sslContext, delegate); 
        schemeRegistry.register(new Scheme("https", socketFactory, 443)); 
    
        DefaultHttpClient client = new DefaultHttpClient(); 
        HttpParams params = client.getParams(); 
        client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, 
          schemeRegistry), params){ 
         protected HttpParams determineParams(HttpRequest req) { 
          HttpParams params = req.getParams(); // req is an HttpRequest object 
          HttpConnectionParams.setSoTimeout(params, 60000); 
          HttpConnectionParams.setConnectionTimeout(params, 60000); 
          return params; 
         } 
        }; 
    
        return client; 
    } 
    

因爲你可以參考這篇文章http://fuking-android.quora.com/Implement-HTTPS-for-android-apps-a-novices-tale我選擇的詳細原因。