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

这件事现在已经困扰了我好几天了。 我已经阅读了很多关于这整个问题的其他问题,但仍然无法继续。

我创建了一个简单的测试应用程序,只是为了在Android上测试SSL。 应用程序只有一个按钮,当单击时,应用程序尝试通过SSL加密连接将“Hello World”发送到我的测试服务器,然后测试服务器以完全相同的短语进行响应。

首先,我使用openssl为我的服务器创建了测试密钥和测试证书。 然后我一直在按照Crazy Bob博客中的说明进行操作。 我直接从Bouncy Castle的网站获得了Bouncy Castle提供商,创建了一个可信赖的密钥库,如Crazy Bob的博客所示,并且我相信这一切都是正确的。

当我尝试运行我的代码时,我得到了exception“IOException:密钥库的错误版本。” 然后我在StackOverflow上发现了这个问题 。 有人建议我应该尝试使用较旧的Bouncy Castle Providers而不是最新的bcprov-jdk15on-147.jar 。 我继续考虑到这一点,实际上最终尝试了从jdk13-146到jdk16-146的每个bcprovider。 仍然每次我都得到相同的“IOExcpetion:错误版本的密钥库”。 例外。

然后我发现了另一个关于StackOverflow上类似问题的问题。 有人设法通过使用512位大小的密钥而不是1024大小的密钥来摆脱该exception。 好吧,我试了一下,什么也没做,但同样的例外。

我现在在这里,想知道接下来该做什么。 我几乎没有想法和谷歌搜索结果。

我的网络代码是疯狂的bob代码的1对1副本,此外应用程序只有处理按钮的活动类。 我正在尝试在API级别7上实现此function。

任何帮助将不胜感激。 谢谢。

2种选择:

  1. 你可以做你做的事情并创建你自己的密钥库,我已经完成了,这里是我存储的代码中的指令(因为它让它工作非常耗时):

    要生成PKS:

    1. 在IIS7中创建证书,然后导出为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 -out C:\ cert.cer -nodes
    3. 编辑文件并删除除—– BEGIN之外的所有内容….结束证书—–重要! 当我得到适当的(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. 创建TRUST ALL KeyStore并忘记所有这些。 基本上,您可以使用任何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); } 

当我尝试向EWS请求时,它与我的问题类似。 您可以参考此链接并下载示例源代码,然后像我的回答一样修改它。 希望这可以帮助!

更新
以下命令对我有用(我大约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 lib。 你可以尝试一下。
另一个创建密钥库的工具: http : //portecle.sourceforge.net/

好吧,我也遇到了同样的情况,为了解决这个问题,我从R4j引用的同一博客文章( http://nelenkov.blogspot.in/2011/12/using-custom-certificate-trust-store-on.html )中获得了帮助。 以下是涉及的步骤:

  1. 创建自定义信任 :我使用Portecle创建密钥库,并从我的服务器导入公钥证书。
  2. 使用密钥对创建自定义密钥库 :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. 然后你就像在nelkov的博客中提到的那样使用它们。 如果您遇到为abc.com颁发证书并且Verifier拒绝www.abc.com的情况,您可能还需要创建自己的自定义AbstractVerifier
  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 。