# AndroidHttps **Repository Path**: liuzy1988/AndroidHttps ## Basic Information - **Project Name**: AndroidHttps - **Description**: 安卓端使用双向认证请求服务器的完整示例 - **Primary Language**: Android - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 52 - **Forks**: 23 - **Created**: 2016-03-17 - **Last Updated**: 2025-06-18 ## Categories & Tags **Categories**: android-modules **Tags**: None ## README AndroidHttps === 安卓端使用双向认证请求服务器的完整示例 前言 --- 众所周知,Http请求包含了地址、端口、请求头、请求体等等。 与服务器的通信交由SocketFactory,而Https请求需要用SSLSocketFactory。 创建SSLSocketFactory需要一个两个KeyStore: 一个是keyStore,里面放着`服务器信任的客户端证书`和`客户端私钥`; 一个是trustStore,里面放着客户端信任的`服务器证书`。 在Java中默认的KeyStore类型是JKS,安卓中默认为BKS。 生成keyStore和trustStore示例 --- ### 方式一(加载P12和BKS文件,通过以下方法得到两个KeyStore) ```java // 把客户端证书和私钥用openssl导出为P12格式 String p12File = "client.p12"; // 你需要知道P12的密码 String p12Pwd = "123456"; // 生成KeyStore,密码为P12的密码 KeyStore keyStore1 = KeyStoreManager.getKeyStoreByP12(ctx, p12File, p12Pwd); // 把服务器证书用keytool工具生成KeyStore并导入其中 String bksFile = "client.bks"; // 你需要知道bks的密码 String bksPwd = "123456"; // 生成TrustStore KeyStore trustStore1 = KeyStoreManager.getTrustStoreByBks(ctx, bksFile, bksPwd); ``` ### 方式二(加载client.pem、client.crt和server.crt,通过以下方法得到两个KeyStore) ```java // 生成你的私钥文件,内容是...BEGIN RSA PRIVATE KEY... String clientPem = "client.pem"; // 根据你的私钥生成客户端证书 String clientCrt = "client.crt"; // 为KeyStore设置一个密码 String keyStorePwd = "123456"; // 生成KeyStore KeyStore keyStore2 = KeyStoreManager.getKeyStoreByCrtPem(ctx, clientCrt, clientPem, keyStorePwd); // 服务器证书 String serverCrt = "server.crt"; // 生成TrustStore KeyStore trustStore2 = KeyStoreManager.getTrustStoreByCrt(ctx, serverCrt); ``` 使用你的keyStore和trustStore初始化SSLSocketFactory --- ### 方式一(初始化HttpsUrlConnection的SSLSocketFactory) ``` // -------------使用HTTPS工具类--------------- // 初始化方法只需要调用一次,如果你信任所有服务器,trustStore传入null即可! HTTPS.init(keyStore, keyStorePwd, trustStore); // 发起请求 new HTTPS().doGET(HTTPS_URL, params); ``` ### 方式二(初始化HttpClient的SSLSocketFactory) ``` // ----------使用HttpClientTool工具类---------- // 初始化方法只需要调用一次,如果你信任所有服务器,trustStore传入null即可! HttpClientTool.init(keyStore, keyStorePwd, trustStore); // 发起请求 HttpClientTool.doGET(HTTPS_URL, params); ``` 重要提示 --- 关于私钥的转换,着实是费了几天时间。 网上有大量资料说明在安卓中如何使用P12和BKS的方式生成keyStore和trustStore。 在项目中,我试图把client.pem读出来转换成与P12相同的PrivateKey,即PKCS8类型的私钥。 我们知道,使用openssl生成的私钥是如下形式,例如项目中的client.pem: ``` -----BEGIN RSA PRIVATE KEY----- ``` 使用openssl很容易完成PKCS8转换: ``` openssl pkcs8 -topk8 -inform PEM -in client.pem -outform PEM -nocrypt -out client_pkcs8.pem ``` 转换后内容如下: ``` -----BEGIN PRIVATE KEY----- ``` 完成上述转换的代码其实相当简单,使用bcprov-jdk1***.jar中的`PemReader`类,可以直接把pem读为`KeyPair`, 然后从`KeyPair`中取出私钥,这个私钥就是我们要的!!! ```java InputStream pem = ctx.getResources().getAssets().open(pemFile); InputStreamReader inReader = new InputStreamReader(pem); PEMReader pemReader = new PEMReader(inReader); KeyPair keyPair = (KeyPair) pemReader.readObject(); PrivateKey privateKey = keyPair.getPrivate(); ``` 使用`PemWriter`可以打印一个密钥,包括BEGIN和END字符串: ```java PemObject obj = new PemObject(keyName, keyBytes); PrintWriter pw = new PrintWriter(System.out); PemWriter pemw = new PemWriter(pw); pemw.writeObject(obj); pw.close(); pemw.close(); ``` 更多 --- 想了解更多关于证书方面的内容,欢迎访问我的另外一个项目 KS [https://git.oschina.net/liuzy1988/KS](https://git.oschina.net/liuzy1988/KS)