首页 > 解决方案 > 如何将 SSL 证书添加到 Android 项目?

问题描述

我对客户端和服务器之间的通信知之甚少,对 SSL 的了解更少,但我参与了一个项目,在该项目中我开发了一个读取服务器上数据的 android 应用程序。我曾经在服务器上打开一个没有任何安全措施的套接字,但我们决定使用 SSL 保护服务器。这样做的人给我发了一个 .crt 文件,它是公钥和一个 .jks 格式的信任库文件。

我被要求在 android 项目中添加此证书。但我找不到如何做到这一点。这就是为什么如果有人能告诉我如何在 Android 项目中添加证书以打开 SSLSocket,我将非常感激。

谢谢

标签: androidsslserver

解决方案


对于像您这样的案例, Google 有专门的指南

这里有一个关于你需要什么的小引述:

未知的证书颁发机构 在这种情况下,发生 SSLHandshakeException 是因为您有一个不受系统信任的 CA。这可能是因为您拥有来自 Android 尚未信任的新 CA 的证书,或者您的应用在没有 CA 的旧版本上运行。更多情况下,CA 是未知的,因为它不是公共 CA,而是由政府、公司或教育机构等组织颁发的私人 CA,供他们自己使用。

幸运的是,您可以教 HttpsURLConnection 信任一组特定的 CA。这个过程可能有点复杂,所以下面是一个从 InputStream 中获取特定 CA 的示例,使用它来创建一个 KeyStore,然后使用它来创建和初始化一个 TrustManager。TrustManager 是系统用来验证来自服务器的证书,并且通过从具有一个或多个 CA 的 KeyStore 创建一个证书,这些将是该 TrustManager 信任的唯一 CA。

给定新的 TrustManager,该示例初始化一个新的 SSLContext,它提供了一个 SSLSocketFactory,您可以使用它来覆盖 HttpsURLConnection 中的默认 SSLSocketFactory。这样,连接将使用您的 CA 进行证书验证。

以下是使用华盛顿大学的组织 CA 的完整示例:

// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
    ca = cf.generateCertificate(caInput);
    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
    caInput.close();
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
    (HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);

因此,只需将您的 crt 文件放入资源文件夹,然后运行此代码,将其更改caInput为:

InputStream caInput = getResources().openRawResource(R.raw.cert);

推荐阅读