I want to add multiple SSL certificates from a ressource file to the Android KeyStore as follow:
if (sslContext==null) {
// loading CA from an InputStream
InputStream is = AVApplication.getContext().getResources().openRawResource(R.raw.wildcard);
String certificates = Converter.convertStreamToString(is);
String certificateArray[] = certificates.split("-----BEGIN CERTIFICATE-----");
for (int i = 1; i < certificateArray.length; i++) {
certificateArray[i] = "-----BEGIN CERTIFICATE-----" + certificateArray[i];
//LogAV.d("cert:" + certificateArray[i]);
// generate input stream for certificate factory
InputStream stream = IOUtils.toInputStream(certificateArray[i]);
// CertificateFactory
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// certificate
Certificate ca;
try {
ca = cf.generateCertificate(stream);
} finally {
is.close();
}
// creating a KeyStore containing our trusted CAs
KeyStore ks = KeyStore.getInstance("BKS");
ks.load(null, null);
ks.setCertificateEntry("av-ca" + i, ca);
// TrustManagerFactory
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
// Create a TrustManager that trusts the CAs in our KeyStore
tmf.init(ks);
// Create a SSLContext with the certificate that uses tmf (TrustManager)
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
}
}
return sslContext;
Only the last certificate of the file works! It seems the certificate overwrites the other one.
File looks like:
-----BEGIN CERTIFICATE-----
cert
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
cert
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
cert
-----END CERTIFICATE-----
I hope somebody can help me! :)
You can install multiple SSL certificates on a domain, but first a word of caution. A lot of people want to know whether you can install multiple SSL certificates on a single domain. The answer is yes.
ssl package and you can use it to implement Android Certificate Pinning. Keep reading for a step-by-step tutorial on how to implement pinning using this component. Load KeyStore with the Certificate file from resources (as InputStream). Get TrustManagerFactory and init it with KeyStore.
This is the most common reason behind SSL certificate errors. If there's a mismatch between the clock on your device and the clock of web server that you're trying to access then SSL certificate of website won't be verified. As a result, you'll get an SSL error.
What Are the Benefits? Certificate pinning offers enhanced control for organizations that wish to custom-design certificate-based authentication and encryption security directly into their online applications and mobile applications.
Thx to @Dan Getz, now it works.
1. Solution with SSL context & Self signed Certificate:
public static SSLContext getSSLContext() throws Exception {
if (sslContext==null) {
// loading CA from an InputStream
InputStream is = AVApplication.getContext().getResources().openRawResource(R.raw.certificates);
String certificates = Converter.convertStreamToString(is);
String certificateArray[] = certificates.split("-----BEGIN CERTIFICATE-----");
// creating a KeyStore containing our trusted CAs
KeyStore ks = KeyStore.getInstance("BKS");
ks.load(null, null);
for (int i = 1; i < certificateArray.length; i++) {
certificateArray[i] = "-----BEGIN CERTIFICATE-----" + certificateArray[i];
//LogAV.d("cert:" + certificateArray[i]);
// generate input stream for certificate factory
InputStream stream = IOUtils.toInputStream(certificateArray[i]);
// CertificateFactory
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// certificate
Certificate ca;
try {
ca = cf.generateCertificate(stream);
} finally {
is.close();
}
ks.setCertificateEntry("av-ca" + i, ca);
}
// TrustManagerFactory
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
// Create a TrustManager that trusts the CAs in our KeyStore
tmf.init(ks);
// Create a SSLContext with the certificate that uses tmf (TrustManager)
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
}
return sslContext;
}
Then using the SSL context:
client = okHttpClient.newBuilder()
.sslSocketFactory(getSslContext(context).getSocketFactory())
.build();
2. Solution with Pinning a not root certificate with OkHttp via fingerprints:
Pinning a non root CA, I'm using the CertificatePinner
from OkHttp (! this does not work for self-signed certificate - root CAs):
CertificatePinner = new CertificatePinner.Builder()
.add(new URL(url).getHost(), "sha256/<certificate1 fingerprint [base64]>")
.add(new URL(url).getHost(), "sha256/<certificate2 fingerprint [base64]>")
.build();
OkHttpClient client;
client = okHttpClient.newBuilder()
.certificatePinner(certificatePinner)
.build();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With