As mentioned inwards a previous post, Android 4.0 (ICS) adds both a organisation UI as well as SDK API's that permit yous add together certificates to the organisation trust store. On all previous version though, the organisation trust shop is read-only as well as in that place is no agency to add together certificates on non-rooted devices. Therefore, if yous desire to connect to a server that is using a certificate non signed yesteryear ane of the CA's included inwards the organisation trust shop (including a self-signed one), yous demand to create as well as work a soul trust shop for the application. That is non peculiarly difficult to do, but 'how to connect to a server amongst a self-signed certificate' is ane of the close asked Android questions on StackOverflow, as well as the park response goes along the lines of 'simply trust all certificates as well as yous are done'. While this volition indeed permit yous connect, as well as mightiness endure OK for testing, it defeats the whole role of using HTTPS: your connexion mightiness endure encrypted but yous conduct maintain no agency of knowing who yous are talking to. This opens the door to man-in-the-middle (MITM) attacks, and, needless to say, is bad practice. In this postal service nosotros volition explore how Android's HTTPS organisation industrial plant pre-ICS as well as demo how to create as well as work a custom certificate trust shop as well as a dynamically configurable
Some background: JSSE
Java, as well as yesteryear extension Android, implement SSL using a framework called Java Secure Socket Extension (JSSE). Influenza A virus subtype H5N1 give-and-take of how SSL as well as JSSE operate is beyond the ambit of this post, but yous tin uncovering a shot introduction to SSL inwards the context of JSSE here. In brief, SSL provides both privacy as well as information integrity (i.e., an encrypted communications channel) as well as authentication of the parties involved. Authentication is implemented using world fundamental cryptography as well as certificates. Each political party presents their certificate, as well as if the other political party trusts it, they negotiate a shared fundamental to encrypt communications using the associated fundamental pairs (public as well as private). JSSE delegates trust decisions to a
One agency to specify the trust anchors is to add together the CA certificates to a Java fundamental shop file, referred to every bit a 'trust store'. The default JSSE
Android as well as
If yous desire to specify your ain organisation trust shop file inwards desktop Java, it is exactly a affair of setting a value to the
If yous straight off work
If nosotros tin modify the laid of trusted certificates using this property, connecting to a server using a custom certificate should endure easy, right? It turns out this is non the case. You tin endeavor it yourself using the sample app: pressing 'Default Connect' volition upshot inwards a 'Trust anchor for certificate path non found' fault regardless of the the world of the 'Set javax.net.ssl.trustStore' checkbox. Influenza A virus subtype H5N1 footling farther investigation reveals that the default
Using your ain trust store: HttpClient
Since nosotros can't work the 'easy way' on Android, nosotros demand to specify the trust shop to work programmatically. This is non difficult either, but commencement nosotros demand to create a fundamental shop file amongst the certificates nosotros need. The sample projection contains a shell script that does this automatically. All yous demand is a recent Bouncy Castle jounce file as well as the openssl ascendence (usually available on Linux systems). Drop the jounce as well as a certificate (in PEM format) inwards the script's directory as well as run it similar this:
This volition calculate the certificate subject's hash as well as work it every bit the alias inwards a Bouncy Castle fundamental shop file (BKS format) created inwards the application's
Apache's HttpClient provides a convenient
Once initialized similar this, the
Using your ain trust store: HttpsURLConnection
Another pop HTTPS API on Android is this is the preferred API from Android 2.3 (Gingerbread) as well as on. Whether to genuinely work is it is, of course, alone upwardly to yous :) It uses JSSE to connect via HTTPS, hence initializing it amongst our ain trust and/or fundamental shop involves creating as well as initializing an
In this instance nosotros are using both a trust shop as well as a fundamental store, but if yous don't demand customer authentication, yous tin exactly top
Creating a dynamic
As mentioned above, a
To address the minute problem, nosotros exactly re-create the trust shop to internal storage when nosotros commencement start the application as well as work that file to initialize our
Using our
Initializing an
You tin cheque that this genuinely industrial plant amongst the 'HttpClient Connect' as well as 'HttpsURLConnection Connect' buttons of the sample application. Both clients are using our custom
Summary
We've shown how the default
TrustManager
.Some background: JSSE
Java, as well as yesteryear extension Android, implement SSL using a framework called Java Secure Socket Extension (JSSE). Influenza A virus subtype H5N1 give-and-take of how SSL as well as JSSE operate is beyond the ambit of this post, but yous tin uncovering a shot introduction to SSL inwards the context of JSSE here. In brief, SSL provides both privacy as well as information integrity (i.e., an encrypted communications channel) as well as authentication of the parties involved. Authentication is implemented using world fundamental cryptography as well as certificates. Each political party presents their certificate, as well as if the other political party trusts it, they negotiate a shared fundamental to encrypt communications using the associated fundamental pairs (public as well as private). JSSE delegates trust decisions to a
TrustManager
class, as well as authentication fundamental alternative to a KeyManager
class. Each SSLSocket
instance created via JSSE has access to those classes via the associated SSLContext
(you tin uncovering a pretty flick here). Each TrustManager
has a laid of trusted CA certificates (trust anchors) as well as makes trust decisions based on those: if the target party's certificate is issued yesteryear ane of the trusted CA's, it is considered trusted itself.One agency to specify the trust anchors is to add together the CA certificates to a Java fundamental shop file, referred to every bit a 'trust store'. The default JSSE
TrustManager
is initialized using the organisation trust shop which is to a greater extent than oftentimes than non a unmarried fundamental shop file, saved to a organisation place as well as pre-populated amongst a laid of major commercial as well as regime CA certificates. I
f yous desire to modify this, yous demand to create an appropriately configured TrustManager
instance, either via a TrustManagerFactory
, or yesteryear direct implementing the X509TrustManager
interface. To brand the full general instance where ane exactly wants to work their ain fundamental shop file to initialize the default TrustManager
and/or KeyManager
, JSSE provides a set of organisation properties to specify the files to use.Android as well as
javax.net.ssl.trustStore
If yous desire to specify your ain organisation trust shop file inwards desktop Java, it is exactly a affair of setting a value to the
javax.net.ssl.trustStore
organisation holding when starting the computer program (usually using the -D
JVM ascendence business parameter). This holding is besides supported on Android, but things operate a footling differently. If yous impress the value of the holding it volition close probable endure /system/etc/security/cacerts.bks
, the organisation trust shop file (pre-ICS; the holding is non onslaught ICS). This value is used to intialize the default TrustManagerFactory
, which inwards plough creates an X.509 certificate-based TrustManager
. You tin impress the electrical flow trust anchors similar this:TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init((KeyStore) null); X509TrustManager xtm = (X509TrustManager) tmf.getTrustManagers()[0]; for (X509Certificate cert : xtm.getAcceptedIssuers()) { String certStr = "S:" + cert.getSubjectDN().getName() + "\nI:" + cert.getIssuerDN().getName(); Log.d(TAG, certStr); }
If yous straight off work
System.setProperty()
to betoken the holding to your ain trust shop file, as well as run the to a higher house code again, yous volition encounter that it outputs the certificates inwards the specified file. Check the 'Set javax.net.ssl.trustStore' checkbox as well as work the 'Dump trusted certs' push of the sample app to endeavor it. If nosotros tin modify the laid of trusted certificates using this property, connecting to a server using a custom certificate should endure easy, right? It turns out this is non the case. You tin endeavor it yourself using the sample app: pressing 'Default Connect' volition upshot inwards a 'Trust anchor for certificate path non found' fault regardless of the the world of the 'Set javax.net.ssl.trustStore' checkbox. Influenza A virus subtype H5N1 footling farther investigation reveals that the default
SSLContext
is already initialized amongst the organisation trust anchors as well as setting the javax.net.ssl.trustStore
holding does non modify this. Why? Because Android pre-loads organisation classes, as well as yesteryear the fourth dimension your application starts, the default SSLContext
is already initialized. Of course, whatever TrustManager
's yous create after setting the holding volition pick it upwardly (see above).Using your ain trust store: HttpClient
Since nosotros can't work the 'easy way' on Android, nosotros demand to specify the trust shop to work programmatically. This is non difficult either, but commencement nosotros demand to create a fundamental shop file amongst the certificates nosotros need. The sample projection contains a shell script that does this automatically. All yous demand is a recent Bouncy Castle jounce file as well as the openssl ascendence (usually available on Linux systems). Drop the jounce as well as a certificate (in PEM format) inwards the script's directory as well as run it similar this:
$ ./importcert.sh cacert.pem
This volition calculate the certificate subject's hash as well as work it every bit the alias inwards a Bouncy Castle fundamental shop file (BKS format) created inwards the application's
raw/
resources directory. The script deletes the fundamental shop file if it already exists, but yous tin easily modify it to append certificates instead. If yous are non the command-line type, yous tin work the Portecle GUI utility to create the fundamental shop file. Apache's HttpClient provides a convenient
SSLSocketFactory
bird that tin endure direct initialized amongst a trust shop file (and a fundamental shop file if customer authentication is needed). All yous demand to do is to register it inwards the scheme registry to handgrip the https
scheme:KeyStore localTrustStore = KeyStore.getInstance("BKS"); InputStream inwards = getResources().openRawResource(R.raw.mytruststore); localTrustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray()); SchemeRegistry schemeRegistry = novel SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory .getSocketFactory(), 80)); SSLSocketFactory sslSocketFactory = novel SSLSocketFactory(trustStore); schemeRegistry.register(new Scheme("https", sslSocketFactory, 443)); HttpParams params = novel BasicHttpParams(); ClientConnectionManager cm = novel ThreadSafeClientConnManager(params, schemeRegistry); HttpClient customer = novel DefaultHttpClient(cm, params);
Once initialized similar this, the
HttpClient
instance volition work our local trust shop when verifying server certificates. If yous demand to work customer authentication every bit well, exactly charge as well as top the fundamental shop containing the client's soul fundamental as well as certificate to the appropriate SSLSocketFactory
constructor. See the sample projection for details as well as work the 'HttpClient SSLSocketFactory Connect' push to test. Note that, when initialized similar this, our HttpClient
volition work only the certificates inwards the specified file, completely ignoring the organisation trust store. Thus connections to say, https://google.com
volition fail. We volition address this later. Using your ain trust store: HttpsURLConnection
Another pop HTTPS API on Android is this is the preferred API from Android 2.3 (Gingerbread) as well as on. Whether to genuinely work is it is, of course, alone upwardly to yous :) It uses JSSE to connect via HTTPS, hence initializing it amongst our ain trust and/or fundamental shop involves creating as well as initializing an
SSLContext
(HttpClient's SSLSocketFactory
does this behind the scenes):KeyStore trustStore = loadTrustStore(); KeyStore keyStore = loadKeyStore(); TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); KeyManagerFactory kmf = KeyManagerFactory .getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, KEYSTORE_PASSWORD.toCharArray()); SSLContext sslCtx = SSLContext.getInstance("TLS"); sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); URL url = novel URL("https://myserver.com"); HttpsURLConnection urlConnection = (HttpsURLConnection) url urlConnection.setSSLSocketFactory(sslCtx.getSocketFactory());
In this instance nosotros are using both a trust shop as well as a fundamental store, but if yous don't demand customer authentication, yous tin exactly top
null
every bit the commencement parameter of SSLContext.init()
. Creating a dynamic
TrustManager
As mentioned above, a
TrustManager
initialized amongst a custom trust shop volition only work the certificates inwards that shop every bit trust anchors: the organisation defaults volition endure completely ignored. Sometimes this is all that is needed, but if yous demand to connect to both your ain server as well as other world servers that work HTTPS (such every bit Twitter, for example), yous volition demand to create 2 carve upwardly instances of HttpClient
or HttpsURLConnection
as well as switch betwixt the two. Additionally, since the trust shop is stored every bit an application resource, in that place is no agency to add together trusted certificates dynamically, yous demand to repackage the application to update the trust anchors. Certainly nosotros tin do ameliorate than that. The commencement job is easily addressed yesteryear creating a custom TrustManager
that delegates certificate checks to the organisation default ane as well as uses the local trust shop if verification fails. Here's how this looks like:public bird MyTrustManager implements X509TrustManager { soul X509TrustManager defaultTrustManager; soul X509TrustManager localTrustManager; soul X509Certificate[] acceptedIssuers; world MyTrustManager(KeyStore localKeyStore) { // init defaultTrustManager using the organisation defaults // init localTrustManager using localKeyStore } world void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { endeavor { defaultTrustManager.checkServerTrusted(chain, authType); } grab (CertificateException ce) { localTrustManager.checkServerTrusted(chain, authType); } } //... }
To address the minute problem, nosotros exactly re-create the trust shop to internal storage when nosotros commencement start the application as well as work that file to initialize our
TrustManager
's. Since the file is owned yesteryear the application, yous tin easily add together as well as take trusted certificates. To examine modifying the trust shop works, re-create a certificate file(s) inwards DER format to the SD card (external storage) origin as well as work the sample application's 'Add certs' as well as 'Remove certs' menus to add together or take it to/from the local trust shop file. You tin as well as hence verify the contents of the file yesteryear using the 'Dump trusted certs' push (don't forget to cheque 'Set javax.net.ssl.trustStore'). To implement this the app exactly uses the JCE KeyStore
API to add together or take certificates as well as relieve the trust shop file:CertificateFactory cf = CertificateFactory.getInstance("X509"); InputStream is = novel BufferedInputStream(new FileInputStream(certFile)); X509Certificate cert = (X509Certificate) cf.generateCertificate(is); String alias = hashName(cert.getSubjectX500Principal()); localTrustStore.setCertificateEntry(alias, cert); FileOutputStream out = novel FileOutputStream(localTrustStoreFile); localTrustStore.store(out, TRUSTSTORE_PASSWORD.toCharArray());
Using our
MyTrustManager
amongst HttpsURLConnection
is non much dissimilar than using the default one:MyTrustManager myTrustManager = novel MyTrustManager(localTrustStore); TrustManager[] tms = novel TrustManager[] { myTrustManager }; SSLContext sslCtx = SSLContext.getInstance("TLS"); context.init(null, tms, null); HttpsURLConnection urlConnection = (HttpsURLConnection) url .openConnection(); urlConnection.setSSLSocketFactory(sslCtx.getSocketFactory());
HttpClient
's SSLSocketFactory
doesn't permit us specify a custom TrustManager
, hence nosotros demand to create our ain SocketFactory
. To brand initialization consistent amongst that of HttpsURLConnection
, nosotros conduct maintain it bring an already initialized SSLContext
as a parameter as well as work it to larn a manufacturing flora that lets us create SSL sockets every bit needed:public bird MySSLSocketFactory implements LayeredSocketFactory { soul SSLSocketFactory socketFactory; soul X509HostnameVerifier hostnameVerifier; world MySSLSocketFactory(SSLContext sslCtx, X509HostnameVerifier hostnameVerifier) { this.socketFactory = sslCtx.getSocketFactory(); this.hostnameVerifier = hostnameVerifier; } //.. @Override world Socket createSocket() throws IOException { render socketFactory.createSocket(); } }
Initializing an
HttpClient
instance is straight off exactly a affair of registering our socket manufacturing flora for the https
scheme:SSLContext sslContext = createSslContext(); MySSLSocketFactory socketFactory = novel MySSLSocketFactory( sslContext, novel BrowserCompatHostnameVerifier()); schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
You tin cheque that this genuinely industrial plant amongst the 'HttpClient Connect' as well as 'HttpsURLConnection Connect' buttons of the sample application. Both clients are using our custom
TrustManager
outlined to a higher house as well as trust anchors are loaded dynamically: adding as well as removing certificates via the card volition direct influence whether yous tin connect to the target server.Summary
We've shown how the default
TrustManager
on pre-ICS Android devices industrial plant as well as how to develop both HttpClient
as well as HttpsURLConnection
to work a local (application-scoped) trust and/or fundamental store. In addition, the sample app provides a custom TrustManager
implementation that both extends the organisation one, as well as supports dynamically adding as well as removing application-specified trust anchors. While this is non every bit flexible every bit the system-wide trust shop introduced inwards ICS, it should endure sufficient for close applications that demand to handle their ain SSL trust store. Do work those examples every bit a starting betoken as well as delight do not work whatever of the trust-all 'solutions' that pop upwardly on StackOverflow every other day.
Tag :
android security
0 Komentar untuk "Droidcedas : Using A Custom Certificate Trust Shop On Android"