也许不是最好的代码,但它有效,它并没有严格回答您所有的问题,但也许您会找到可以使用的部分。
你的流程很好,我也在做几乎同样的事情。
我将密钥保存在动态创建的密钥库中。另外,我有密钥库,其中包含使用 openssl 工具创建的可信证书。
对于通信,我使用了 okHttp + 改造
https://github.com/square/okhttp
https://github.com/square/retrofit
产生KeyPair
:
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.genKeyPair();
return keyPair;
}
生成 CSR:
private static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair) throws IOException, OperatorCreationException {
String principal = "CN=company1, OU=company1, O=company1, C=GB";
AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder()
.find("SHA1WITHRSA");
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);
PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(
principal), keyPair.getPublic());
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
extensionsGenerator.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(true));
extensionsGenerator.addExtension(X509Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign
| KeyUsage.cRLSign));
csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate());
PKCS10CertificationRequest csr = csrBuilder.build(signer);
return csr;
}
发送csr(您可能需要将其转换为pem格式),接收证书。
初始化密钥库:
KeyStore store = KeyStore.getInstance("BKS");
InputStream in;
try {
in = App.getInstance().getApplicationContext().openFileInput(filename);
try {
store.load(in, password);
} finally {
in.close();
}
} catch (FileNotFoundException e) {
//create new keystore
store.load(null, password);
}
初始化信任库:
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream in = App.getInstance().getApplicationContext().getResources().openRawResource(R.raw.truststore);
try {
trustStore.load(in, trustorePassword);
} finally {
in.close();
}
将密钥添加到密钥库(确保您的私钥和证书匹配,如果不匹配,密钥库不会抛出异常,并且使用 okHttp 这可能会导致 libssl 崩溃(仅在 api 低于 4.1 的设备上):
keyStore.setKeyEntry(alias, privateKey, password, new X509Certificate[]{certificate});
使用自己的创建 okHttpClientSSLContext
:
OkHttpClient client = new OkHttpClient();
KeyStore keyStore = App.getInstance().getKeyStoreUtil().getKeyStore();
KeyStore trustStore = App.getInstance().getKeyStoreUtil().getTrustStore();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyStorePassword);
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
client.setSslSocketFactory(sslCtx.getSocketFactory());
client.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
查看 Nikolay Elenkov 博客,您还可以找到许多有用的信息以及源代码。
- http://nelenkov.blogspot.com/
- http://nelenkov.blogspot.com/2011/11/using-ics-keychain-api.html
- http://nelenkov.blogspot.in/2011/12/ics-trust-store-implementation.html
- http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html
- http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html
- http://nelenkov.blogspot.com/2013/08/credential-storage-enhancements-android-43.html
@edit
发布您的例外情况
@edit2
在你的情况下,你需要提取你的X509Certificate
从 Web 服务响应中,将其存储在密钥库中,并使用用于生成 CSR 请求的私钥,并将 CA 证书存储在另一个将用作信任库的密钥库中。 (可以是相同的密钥库,但不推荐)。