简体   繁体   English

如何在Android中使用自签名SSL证书

[英]How to use a self signed SSL certificate in Android

This thing has been bugging me for couple days now. 这东西已经困扰我好几天了。 I've read lots of other questions about this whole issue and still haven't been able to proceed. 我已经阅读了许多有关整个问题的其他问题,但仍然无法进行。

I've created a simple test application just to test SSL on Android. 我创建了一个简单的测试应用程序,仅用于在Android上测试SSL。 The application has only one button and when clicked the application tries to send "Hello World" over SSL encrypted connection to my test server, which then responds with the exact same phrase. 该应用程序只有一个按钮,当单击该应用程序时,它尝试通过SSL加密连接将“ Hello World”发送到我的测试服务器,然后以完全相同的短语进行响应。

First I created a test key and test certificate for my server using openssl. 首先,我使用openssl为服务器创建了测试密钥和测试证书。 Then I've been following the instructions showed in Crazy Bob's blog . 然后,我一直按照Crazy Bob的博客中显示的说明进行操作。 I got the Bouncy Castle provider directly from Bouncy Castle's site, created a trusted keystore as shown on Crazy Bob's blog and got everything right at that point I believe. 我直接从Bouncy Castle的网站上获得Bouncy Castle提供程序,创建了一个受信任的密钥库,如Crazy Bob的博客所示,并且在那时我认为一切都正确。

When I tried to run my code, I got the exception "IOException: Wrong version of key store." 当我尝试运行代码时,出现异常“ IOException:密钥存储版本错误”。 Then I found this question on StackOverflow. 然后我在StackOverflow上发现了这个问题 There it was suggested that I should try using older Bouncy Castle Providers rather than the newest bcprov-jdk15on-147.jar . 有人建议我应该尝试使用较旧的Bouncy Castle Provider,而不要使用最新的bcprov-jdk15on-147.jar I went on with this in mind and actually ended up trying every bcprovider from jdk13-146 to jdk16-146. 我继续考虑这一点,实际上最终尝试了从jdk13-146到jdk16-146的每个bcprovider。 Still every time I got the same "IOExcpetion: wrong version of key store." 每次我都得到相同的“ IOExcpetion:密钥存储的版本错误”。 exception. 例外。

Then I found yet another question about similar problem on StackOverflow. 然后,我在StackOverflow上发现了另一个类似问题的问题。 There someone had managed to get rid of that exception by using 512 bit sized key instead of 1024 sized key. 那里有人设法通过使用512位大小的密钥而不是1024位大小的密钥来摆脱该异常。 Well I gave it a try and accomplished nothing, but the same exception. 好吧,我尝试了一下,却没有做任何事情,只是有一个例外。

So here I am now, wondering what to do next. 所以我现在在这里,想知道下一步该怎么做。 I'm pretty much running out of ideas and google search results. 我的想法和Google搜索结果几乎用完了。

My web code is 1 on 1 copy of crazy bob's code and besides that the application has only the activity class that handles the button only. 我的网络代码是疯狂鲍勃代码的一对一副本,此外,该应用程序仅具有仅处理按钮的活动类。 I'm trying to implement this on API level 7. 我正在尝试在API级别7上实现此功能。

Any help would be greatly appreciated. 任何帮助将不胜感激。 Thanks. 谢谢。

2 choices: 2个选择:

  1. You can do what you do and create your own key store and I've done that, here is instructions from my code that I stored (because it was so time consuming to get it to work): 您可以执行您的操作并创建自己的密钥存储,而我已经完成了,这是我存储的代码中的说明(因为使其工作起来非常耗时):

    To generate PKS: 生成PKS:

    1. Created cert in IIS7 and then exported as pfx. 在IIS7中创建证书,然后导出为pfx。 Follow instruction on SelfSSL: http://www.robbagby.com/iis/self-signed-certificates-on-iis-7-the-easy-way-and-the-most-effective-way/ 1a. 请遵循有关SelfSSL的说明: http ://www.robbagby.com/iis/self-signed-certificates-on-iis-7-the-easy-way-and-the-最有效的方式/ 1a。 Download tool: http://cid-3c8d41bb553e84f5.skydrive.live.com/browse.aspx/SelfSSL 1b. 下载工具: http : //cid-3c8d41bb553e84f5.skydrive.live.com/browse.aspx/SelfSSL 1b。 Run: SelfSSL /N:CN=mydomainname /V:1000 /S:1 /P:8081 I use port 8181 on my server 1c. 运行:SelfSSL / N:CN = mydomainname / V:1000 / S:1 / P:8081我在服务器1c上使用端口8181。 Export from IIS manager to cert.pfx 从IIS管理器导出到cert.pfx
    2. Run command line in SSL to convert file into X.509: openssl pkcs12 -in C:\\cert.pfx -out C:\\cert.cer -nodes 在SSL中运行命令行以将文件转换为X.509:openssl pkcs12 -in C:\\ cert.pfx -out C:\\ cert.cer -nodes
    3. Edit file and delete all except -----BEGIN.... END CERTIFICATE----- IMPORTANT! 编辑文件并删除除----- BEGIN ....以外的所有内容。结束证书-----重要! It was working when I got proper (5) amount of dashes and put tags and data on separate lines 当我得到适当(5)的破折号并将标记和数据放在单独的行中时,它就可以工作
    4. use keytool. 使用keytool。 C:\\Java\\JDK\\bcprov.jar was downloaded separately 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 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. Create TRUST ALL KeyStore and forget about all this. 创建TRUST ALL KeyStore,然后将其全部遗忘。 Basically, you can use any SSL without errors. 基本上,您可以使用任何没有错误的SSL。 Just disable it in production if you really care. 如果您真的很在意,请在生产中禁用它。 Here is code I use to get SSL client prepared (assuming you use Apache Http client) 这是我用来准备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); } 

It is similar my question when I try to request to EWS. 当我尝试向EWS请求时,这与我的问题类似。 You can refer to this link and download example source code then modify it like my answer. 您可以参考此链接并下载示例源代码,然后像我的答案一样对其进行修改。 Hope this helps! 希望这可以帮助!

Update : 更新
The following command worked for me (I tried it about 2 months ago): 以下命令对我有用(大约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

You can see, I use bcprov-jdk16-145.jar and openssl lib. 可以看到,我使用bcprov-jdk16-145.jar和openssl lib。 You can try it. 你可以试试。
Another tool to create keystore: http://portecle.sourceforge.net/ 创建密钥库的另一个工具: http : //portecle.sourceforge.net/

Well I also faced this same situation and to solve it I took help from same blog post( http://nelenkov.blogspot.in/2011/12/using-custom-certificate-trust-store-on.html ) referred by R4j . 好吧,我也遇到了同样的情况,为了解决这个问题,我从R4j推荐的同一篇博客文章( http://nelenkov.blogspot.in/2011/12/using-custom-certificate-trust-store-on.html )获得了帮助。 Following are the steps involved : 以下是涉及的步骤:

  1. Create custom trustore : I used Portecle to create a keystore and imported Public Key Certificate from my server into it. 创建自定义受托人 :我使用Portecle创建了密钥库,并将服务器中的公钥证书导入其中。
  2. Create custom keystore with keypair : keytool -genkeypair -alias sample -keyalg RSA -sigalg SHA1withRSA -dname "CN=Nazgul, OU=Assault, O=Sauron Enterprises, L=Mordor, ST=Middle Earth, C=ME" -keypass welcome123 -validity 365 -storetype pkcs12 -keystore g:\\mordor_key_store.pfx -storepass welcome123 -keysize 2048 使用密钥对创建自定义密钥库 :keytool -genkeypair -alias sample -keyalg RSA -sigalg SHA1withRSA -dname“ CN = Nazgul,OU = Assault,O = Sauron Enterprises,L = Mordor,ST = Middle Earth,C = ME” -keypass welcome123 -validity 365 -storetype pkcs12 -keystore g:\\ mordor_key_store.pfx -storepass welcome123 -keysize 2048
  3. You then use them as mentioned in nelkov's blog. 然后,按照nelkov的博客中所述使用它们。 You may also need to create your own custom AbstractVerifier in case you land into a situation where certificate is issued for abc.com and the Verifier rejects www.abc.com 如果您陷入了为abc.com颁发证书而验证者拒绝www.abc.com的情况,则可能还需要创建自己的自定义AbstractVerifier
  4. Finally to create secure HTTPClient you can do something like this: 最后,要创建安全的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; } 

For detailed reasons of my choices you can refer to this post http://fuking-android.quora.com/Implement-HTTPS-for-android-apps-a-novices-tale . 出于我选择的详细原因,您可以参考这篇文章http://fuking-android.quora.com/Implement-HTTPS-for-android-apps-a-novices-tale

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM