Reputation: 6989
disclaimer it is self Q&A question
Several times I faced with situation when our customers bought a certificate considered as "trusted" on iOS, but unfortunately on Android it didn't work.
What is the cause and how to solve it?
Upvotes: 0
Views: 1665
Reputation: 6989
The short answer is buy common trusted certificate.
The reasons is trust store on Android devices contains different set of trusted certificates -- IOS and Android trusted certificates are different.
It can be described on sets:
A -- android trusted certificates
I -- iOS trusted certificates
AI -- intersection of trusted certificates
Therefore, we need an intersection of those two platforms.
However, this issue becomes more complicated because set of trusted certificates varys by OS version for both Android and iOS. It means we will need to look through all supported platforms and all their supported versions to find common set of supported certificates.
For iOS the list of trusted certificates are available on their official site list of supported iOS certificates
For Android I don't find the same list but it is possible to get it from runtime by code below.
public List<CertificateDto> getCertificates() {
List<CertificateDto> result = new ArrayList<>();
try {
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
trustManagerFactory.init((KeyStore) null);
X509TrustManager xtm = (X509TrustManager) trustManagerFactory.getTrustManagers()[0];
for (X509Certificate cert : xtm.getAcceptedIssuers()) {
PublicKey publicKey = cert.getPublicKey();
int leyLength = 0;
if (publicKey instanceof RSAPublicKey) {
leyLength = ((RSAPublicKey) publicKey).getModulus().bitLength();
} else if (publicKey instanceof DSAPublicKey) {
leyLength = ((DSAPublicKey) publicKey).getY().bitLength();
}
CertNameToValidNameConverter validNameConverter = new CertNameToValidNameConverter();
CertificateDto certificate = new CertificateDto();
certificate.setSubjectName(validNameConverter.convert(cert.getSubjectDN().getName()));
certificate.setIssuerName(validNameConverter.convert(cert.getIssuerDN().getName()));
certificate.setKeyLength(leyLength);
certificate.setTypeAlg(cert.getSigAlgName());
certificate.setExpirationDate(cert.getNotAfter().getTime());
result.add(certificate);
}
} catch (NoSuchAlgorithmException e) {
Log.e(App.TAG, "Failed obtain list of certificates", e);
} catch (KeyStoreException e) {
Log.e(App.TAG, "Failed obtain list of certificates", e);
}
return result;
}
When you get the list of certificates from your supported Android OS, you will need to write script to look through all certificates and compare it with another list from different supported Android version and after that with iOS versions as well. You will need compare certificate name, issuer name, algorithm type, sign algorithm and length of the key. Expiration date is also used for validation but you can omit it.
I implemented this script by parsing certificates from excel for IOS 8,9 and Android 6.0, 4.4 and 4.1.
The final list of certificates you can find below. From ~220 IOS certificates and ~150 certificates you can use only ~65 certificates for both platform
list of supported certificates for both Android and iOS (google drive link)
Upvotes: 1