有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

首先,我使用openssl为我的服务器创建了一个测试密钥和测试证书。然后我一直遵循Crazy Bob's blog中的说明。我直接从Bouncy Castle的网站上获得了Bouncy Castle提供商,创建了一个可信的密钥库,如疯狂鲍勃的博客所示,我相信在这一点上一切都是正确的

当我试图运行我的代码时,我得到了异常“IOException:密钥存储的错误版本”然后我在StackOverflow上找到了this question。有人建议我应该尝试使用较旧的Bouncy Castle提供者,而不是最新的bcprov-jdk15on-147。jar。我考虑到了这一点,实际上最终尝试了从jdk13-146到jdk16-146的每一个bcprovider。但每次我都会收到同样的“IoException:密钥存储的错误版本”例外

然后我在StackOverflow上发现了类似的问题。有人设法通过使用512位大小的密钥而不是1024位大小的密钥来消除该异常。嗯,我试了一下,什么也没做,但还是一样的例外

所以我现在在这里,想知道下一步该做什么。我的想法和谷歌搜索结果都快用完了

我的web代码是crazy bob代码的1对1副本,除此之外,应用程序只有只处理按钮的activity类。我试图在API级别7上实现这一点

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


共 (3) 个答案

  1. # 1 楼答案

    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。Run:SelfSSL/N:CN=mydomainname/V:1000/S:1/P:8081 我在服务器上使用端口8181 1c。从IIS管理器导出到cert.pfx
      2. 在SSL中运行命令行以将文件转换为X.509: openssl pkcs12-in C:\cert.pfx-out C:\cert.cer-nodes
      3. 编辑文件并删除除“开始…”之外的所有内容。。。。结束证书-重要!当我得到适当数量的破折号并将标记和数据放在单独的行上时,它就开始工作了
      4. 使用键盘工具。C:\Java\JDK\bcprov。jar是单独下载的 C:\Users>;keytool-import-v-trustcacerts-alias key\u alias-file C:\cert.cer-keystore C:\mystore。bks-商店类型bks-供应商组织。弹跳船舱。jce。供应商。BouncyCastleProvider-providerpath C:\Java\JDK\bcprov。jar-storepass 123456
    2. 创建信任所有密钥库并忘记所有这些。基本上,您可以无错误地使用任何SSL。只要在生产中禁用它,如果你真的在乎的话。下面是我用来准备SSL客户端的代码(假设您使用ApacheHTTP客户端)

      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);
      }
      
  2. # 2 楼答案

    当我试图请求EWS时,情况类似。您可以参考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/

  3. # 3 楼答案

    我也面临同样的情况,为了解决这个问题,我从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=sautch,O=Sauron Enterprises,L=Mordor,ST=Middle Earth,C=ME”—密钥传递欢迎123-validity 365-storetype pkcs12-密钥库g:\Mordor\u key\u store。pfx-storepass welcome123-按键尺寸2048
    3. 然后,您可以按照内尔科夫的博客中所述使用它们。您可能还需要创建自己的自定义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