我正在开发一个企业级的android应用程序,因此在我的测试阶段,有必要在客户端(android模拟器/测试电话)和服务器之间创建一个安全连接,即使服务器的证书是自签名的,而comp正在购买一个合法的证书。任何(我暂时无法控制的事情)。
当然,我需要信任服务器的自签名证书及其证书颁发机构,这是android操作系统本机不信任的。我几乎一字不差地跟着。
我目前面临的问题是,我无法访问我的.crt文件,正如google示例中的这一行所示:

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

代替上述内容,我使用:
InputStream caInput = new BufferedInputStream(
getResources().openRawResource(R.raw.mycrtfile));

打开从InputStream派生的mycrtfile.crt,其中.crt文件存在于/res/raw/mycrtfile.crt中。但是,我在那条线上得到一个NullPointerException
与存储在InputStream目录中的原始资源相比,是否有更好的方法来存储和访问需要作为FileInputStreamres加载的cert文件?

最佳答案

有不同的方法可以解决你的问题,但我用的是:
所有步骤都在这个链接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。-现在你将使用密钥工具(KiGooT附带Java SDK)。你应该在包含javac的目录中找到它来生成我们的密钥存储库,并确保它工作到你的CMD并键入“KioTo工具”,你将看到可用的命令,它可以工作,或者你可以访问“C:\程序文件(x86)\java\jRe7\bin >键工具”。
4.-现在一切就绪,我们可以使用以下命令行生成密钥库:
keytool-importcert-v-trustcacerts-file“c:\bks/mycrtfile.crt”-别名证书-keystore“c:\bks/keystore.bks”-提供程序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”-提供程序org.bouncycastle.jce.provider.bouncycastleprovider-providerpath“c:\ bks/prov-jdk15on-146.jar”-storetype bks-storepass mysecret
4.2-在此之后,您将看到如下输出:
rootca,2010年10月22日,trustedCertEntry,指纹(md5):24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93
Intermediateca,2010年10月22日,TrustedCertEntry,指纹(MD5):98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43
这意味着它是正确导入的。
5.-在此之后,如果您转到bks文件夹,您将看到keystore.bks文件,这意味着我们正在路上。
6.-现在我们进入安卓部分。在项目中,检查是否有“raw”文件夹,如果没有在res下创建此文件夹,则它必须位于project/res/raw中。
7.-将keystore.bks文件复制到原始文件夹中。一切都准备好了,让我们进入代码。
8.--现在我们将创建一个类来阅读和信任我们的密钥库:

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=新客户端(this);
///设置到httpclient。
就这样,你只会相信你的证书。我希望这个解释能帮助你或任何有同样问题的人。

09-28 06:33