The goal
I\'m working on implementing communication with Client-Certificate.
Step 1: Create a PKCS#10 request (CSR) and give it to the my se
Maybe not the best code, but it works, it does not strictly answer all you questions but maybe you will find pieces you can use.
Your flow is good, I'm doing the almost the same thing.
I'm keeping my keys in dynamically created keystore. Additionaly i have keystore with trusted certificates created with openssl tool.
For communication I've used okHttp + retrofit
https://github.com/square/okhttp https://github.com/square/retrofit
Generate KeyPair
:
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.genKeyPair();
return keyPair;
}
Generate 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;
}
Send csr (you may need to convert it to pem format), receive certificate .
Init keystore:
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);
}
Init truststore:
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream in = App.getInstance().getApplicationContext().getResources().openRawResource(R.raw.truststore);
try {
trustStore.load(in, trustorePassword);
} finally {
in.close();
}
Add key to keystore (make sure your private key, and certificate match, keystore won't throw exception if they don't, and with okHttp this can cause libssl crashes (only on devices with api below 4.1):
keyStore.setKeyEntry(alias, privateKey, password, new X509Certificate[]{certificate});
Create okHttpClient with its own SSLContext
:
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);
Look at Nikolay Elenkov blog, you can find many usefull informations with source code as well.
@edit
Post your exception
@edit2
In your case you need to extract your X509Certificate
from webservice response, store it in keystore with privatekey used for generating csr request and store CA cert in another keystore which will work as truststore. (It can be the same keystore, but it's not recommended).