使用keytool生成自签证书
生成密钥库与自签名证书
keytool -genkeypair -alias mydomain -keyalg RSA -keysize 2048 -validity 365 -keystore mydomain.keystore
参数解释:
-genkeypair
:生成密钥对。-alias
:证书别名,通常使用域名。-keyalg
:密钥算法,这里使用 RSA。-keysize
:密钥大小,2048位。-validity
:证书有效期,这里是365天。-keystore
:指定密钥库的名称。-dname
:指定证书拥有者的信息。-storepass
和-keypass
:分别指定密钥库和密钥的密码。
导出证书
keytool -exportcert -alias mydomain -keystore mydomain.keystore -file mydomain.crt
参数解释:
-exportcert
:导出证书-file
:指定导出的证书的文件名
转换格式
PEM
Nginx 默认不支持直接使用 Java 的密钥库格式,需要将私钥转换为 PEM 格式
keytool -importkeystore -srckeystore mydomain.keystore -destkeystore mydomain.p12 -deststoretype PKCS12
openssl pkcs12 -in mydomain.p12 -nocerts -nodes -out mydomain.key
mydomain.key
是Nginx可以直接使用的PEM格式的私钥文件
BKS
Android 默认使用 Bouncy Castle 的 BKS 格式作为其密钥库格式
需要使用Bouncy Castle 提供的 bctls-jdk15on
库进行转换
# 将.crt转换为.pem
openssl x509 -in mydomain.crt -out mydomain.pem -outform PEM
# 使用keytool创建bks文件
keytool -importcert -alias mydomain -file mydomain.pem -keystore mydomain.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath path/to/bcprov-jdk15on-<version>.jar -storepass mypassword
将生成的 mydomain.bks
文件复制到 Android 项目的 assets
文件夹中即可使用
public static SSLSocketFactory getSocketFactory(Context context) throws Exception {
// 读取 BKS 文件
InputStream inputStream = context.getAssets().open("mydomain.bks");
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(inputStream, "mypassword".toCharArray());
// 使用 KeyStore 创建一个 TrustManager
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// 使用 TrustManager 初始化 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
public static void doHttpsRequest(String urlString) throws Exception {
URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
// 设置自定义的 SSLSocketFactory
urlConnection.setSSLSocketFactory(getSocketFactory(context));
// 其他配置...
// 发起请求
urlConnection.connect();
// 读取响应...
urlConnection.disconnect();
}