android - 如何将 SSL 证书添加到 Android 项目?

标签 android ssl server

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

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

谢谢

最佳答案

Google 有一个 special guide对于像您这样的情况。

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

Unknown certificate authority In this case, the SSLHandshakeException occurs because you have a CA that isn't trusted by the system. It could be because you have a certificate from a new CA that isn't yet trusted by Android or your app is running on an older version without the CA. More often a CA is unknown because it isn't a public CA, but a private one issued by an organization such as a government, corporation, or education institution for their own use.

Fortunately, you can teach HttpsURLConnection to trust a specific set of CAs. The procedure can be a little convoluted, so below is an example that takes a specific CA from an InputStream, uses it to create a KeyStore, which is then used to create and initialize a TrustManager. A TrustManager is what the system uses to validate certificates from the server and—by creating one from a KeyStore with one or more CAs—those will be the only CAs trusted by that TrustManager.

Given the new TrustManager, the example initializes a new SSLContext which provides an SSLSocketFactory you can use to override the default SSLSocketFactory from HttpsURLConnection. This way the connection will use your CAs for certificate validation.

Here is the example in full using an organizational CA from the University of Washington:

// 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);

关于android - 如何将 SSL 证书添加到 Android 项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50212374/

相关文章:

Android:在 LinearLayout 上绘制边框

android - 将 TextView 置于相对布局中

java - 具有相同公钥的服务器和客户端 SSL 证书

android - 如何将android的相机设置为ffmpeg的输入

ruby-on-rails - 服务器已经在运行

Android:打开 VPN 设置 Activity 的操作

android - 如何以编程方式通过 tcp 启动 adb 服务器

ssl - Play Store Alert - onReceivedSSLError 的不安全实现

Azure 前门 SSL 证书更新

linux - 如何在没有大堆栈的情况下在 2 个不同的 Centos 主机上建立 2 个服务之间的依赖关系?