1page.title=Security with HTTPS and SSL
2page.tags=network,certificates
3
4page.article=true
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9<h2>In this document</h2>
10<ol class="nolist">
11  <li><a href="#Concepts">Concepts</a></li>
12  <li><a href="#HttpsExample">An HTTP Example</a></li>
13  <li><a href="#CommonProblems">Common Problems Verifying Server Certificates</a>
14    <ol class="nolist">
15      <li><a href="#UnknownCa">Unknown certificate authority</a></li>
16      <li><a href="#SelfSigned">Self-signed server certificate</a></li>
17      <li><a href="#MissingCa">Missing intermediate certificate authority</a></li>
18    </ol>
19  </li>
20  <li><a href="#CommonHostnameProbs">Common Problems with Hostname Verification</a></li>
21  <li><a href="#WarningsSslSocket">Warnings About Using SSLSocket Directly</a></li>
22  <li><a href="#Blacklisting">Blacklisting</a></li>
23  <li><a href="#Pinning">Pinning</a></li>
24  <li><a href="#ClientCert">Client Certificates</a></li>
25  <li><a href="#nogotofail">Nogotofail: Network Security Testing</a></li>
26</ol>
27
28
29<h2>See also</h2>
30<ul>
31<li><a href="http://source.android.com/tech/security/index.html">Android
32Security Overview</a></li>
33<li><a href="{@docRoot}guide/topics/security/permissions.html">Permissions</a></li>
34</ul>
35</div></div>
36
37
38
39<p>The Secure Sockets Layer (SSL)&mdash;now technically known as <a
40href="http://en.wikipedia.org/wiki/Transport_Layer_Security">Transport Layer Security
41(TLS)</a>&mdash;is a
42common building block for encrypted communications between clients and servers. It's possible that
43an application might use SSL incorrectly such that malicious entities may
44be able to intercept an app's data over the network. To help you ensure that this does not happen
45to your app, this article highlights the common pitfalls when using secure network protocols and addresses some larger concerns about using <a
46href="http://en.wikipedia.org/wiki/Public-key_infrastructure">Public-Key Infrastructure (PKI)</a>.
47
48
49<h2 id="Concepts">Concepts</h2>
50
51<p>In a typical SSL usage scenario, a server is configured with a certificate containing a
52public key as well as a matching private key. As part of the handshake between an SSL client
53and server, the server proves it has the private key by signing its certificate with <a
54href="http://en.wikipedia.org/wiki/Public-key_cryptography">public-key cryptography</a>.</p>
55
56<p>However, anyone can generate their own certificate and private key, so a simple handshake
57doesn't prove anything about the server other than that the server knows the private key that
58matches the public key of the certificate. One way to solve this problem is to have the client
59have a set of one or more certificates it trusts. If the certificate is not in the set, the
60server is not to be trusted.</p>
61
62<p>There are several downsides to this simple approach. Servers should be able to
63upgrade to stronger keys over time ("key rotation"), which replaces the public key in the
64certificate with a new one. Unfortunately, now the client app has to be updated due to what
65is essentially a server configuration change. This is especially problematic if the server
66is not under the app developer's control, for example if it is a third party web service. This
67approach also has issues if the app has to talk to arbitrary servers such as a web browser or
68email app.</p>
69
70<p>In order to address these downsides, servers are typically configured with certificates
71from well known issuers called <a
72href="http://en.wikipedia.org/wiki/Certificate_authority">Certificate Authorities (CAs)</a>.
73The host platform generally contains a list of well known CAs that it trusts.
74As of Android 4.2 (Jelly Bean), Android currently contains over 100 CAs that are updated
75in each release. Similar to a server, a CA has a certificate and a private key. When issuing
76a certificate for a server, the CA <a
77href="http://en.wikipedia.org/wiki/Digital_signature">signs</a>
78the server certificate using its private key. The
79client can then verify that the server has a certificate issued by a CA known to the platform.</p>
80
81<p>However, while solving some problems, using CAs introduces another. Because the CA issues
82certificates for many servers, you still need some way to make sure you are talking to the
83server you want. To address this, the certificate issued by the CA identifies the server
84either with a specific name such as <em>gmail.com</em> or a wildcarded set of
85hosts such as <em>*.google.com</em>. </p>
86
87<p>The following example will make these concepts a little more concrete. In the snippet below
88from a command line, the <a href="http://www.openssl.org/docs/apps/openssl.html">{@code openssl}</a>
89tool's {@code s_client} command looks at Wikipedia's server certificate information. It
90specifies port 443 because that is the default for <acronym title="Hypertext Transfer
91Protocol Secure">HTTPS</acronym>. The command sends
92the output of {@code openssl s_client} to {@code openssl x509}, which formats information
93about certificates according to the <a
94href="http://en.wikipedia.org/wiki/X.509">X.509 standard</a>. Specifically,
95the command asks for the subject, which contains the server name information,
96and the issuer, which identifies the CA.</p>
97
98<pre class="no-pretty-print">
99$ openssl s_client -connect wikipedia.org:443 | openssl x509 -noout -subject -issuer
100<b>subject=</b> /serialNumber=sOrr2rKpMVP70Z6E9BT5reY008SJEdYv/C=US/O=*.wikipedia.org/OU=GT03314600/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - RapidSSL(R)/<b>CN=*.wikipedia.org</b>
101<b>issuer=</b> /C=US/O=GeoTrust, Inc./CN=<b>RapidSSL CA</b>
102</pre>
103
104<p>You can see that the certificate was issued for servers matching <em>*.wikipedia.org</em> by
105the RapidSSL CA.</p>
106
107
108
109<h2 id="HttpsExample">An HTTPS Example</h2>
110
111<p>Assuming you have a web server with a
112certificate issued by a well known CA, you can make a secure request with code as
113simple this:</p>
114
115<pre>
116URL url = new URL("https://wikipedia.org");
117URLConnection urlConnection = url.openConnection();
118InputStream in = urlConnection.getInputStream();
119copyInputStreamToOutputStream(in, System.out);
120</pre>
121
122<p>Yes, it really can be that simple. If you want to tailor the HTTP request, you can cast to
123an {@link java.net.HttpURLConnection}. The Android documentation for
124{@link java.net.HttpURLConnection} has further examples about how to deal with request
125and response headers, posting content, managing cookies, using proxies, caching responses,
126and so on. But in terms of the details for verifying certificates and hostnames, the Android
127framework takes care of it for you through these APIs.
128This is where you want to be if at all possible. That said, below are some other considerations.</p>
129
130
131
132<h2 id="CommonProblems">Common Problems Verifying Server Certificates</h2>
133
134<p>Suppose instead of receiving the content from {@link java.net.URLConnection#getInputStream
135getInputStream()}, it throws an exception:</p>
136
137<pre class="no-pretty-print">
138javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
139        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
140        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
141        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
142        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
143        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
144        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
145        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
146        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
147        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
148</pre>
149
150<p>This can happen for several reasons, including:
151<ol>
152  <li><a href="#UnknownCa">The CA that issued the server certificate was unknown</a></li>
153  <li><a href="#SelfSigned">The server certificate wasn't signed by a CA, but was self signed</a></li>
154  <li><a href="#MissingCa">The server configuration is missing an intermediate CA</a></li>
155</ol>
156
157<p>The following sections discuss how to address these problems while keeping your
158connection to the server secure.
159
160
161
162<h3 id="UnknownCa">Unknown certificate authority</h3>
163
164<p>In this case, the {@link javax.net.ssl.SSLHandshakeException} occurs
165because you have a CA that isn't trusted by the system. It could be because
166you have a certificate from a new CA that isn't yet trusted by Android or your app is
167running on an older version without the CA. More often a CA is unknown because it isn't a
168public CA, but a private one issued by an organization such as a government, corporation,
169or education institution for their own use.</p>
170
171<p>Fortunately, you can teach {@link javax.net.ssl.HttpsURLConnection}
172to trust a specific set of CAs. The procedure
173can be a little convoluted, so below is an example that takes a specific CA from
174an {@link java.io.InputStream}, uses it to create a {@link java.security.KeyStore},
175which is then used to create and initialize a
176{@link javax.net.ssl.TrustManager}. A {@link javax.net.ssl.TrustManager} is what the system
177uses to validate certificates from the server
178and&mdash;by creating one from a {@link java.security.KeyStore} with one or more CAs&mdash;those
179will be the only CAs trusted by that {@link javax.net.ssl.TrustManager}.</p>
180
181<p>Given the new {@link javax.net.ssl.TrustManager},
182the example initializes a new {@link javax.net.ssl.SSLContext} which provides
183an {@link javax.net.ssl.SSLSocketFactory} you can use to override the default
184{@link javax.net.ssl.SSLSocketFactory} from
185{@link javax.net.ssl.HttpsURLConnection}. This way the
186connection will use your CAs for certificate validation.</p>
187
188<p>Here is the example in
189full using an organizational CA from the University of Washington:</p>
190
191<pre>
192// Load CAs from an InputStream
193// (could be from a resource or ByteArrayInputStream or ...)
194CertificateFactory cf = CertificateFactory.getInstance("X.509");
195// From https://www.washington.edu/itconnect/security/ca/load-der.crt
196InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
197Certificate ca;
198try {
199    ca = cf.generateCertificate(caInput);
200    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
201} finally {
202    caInput.close();
203}
204
205// Create a KeyStore containing our trusted CAs
206String keyStoreType = KeyStore.getDefaultType();
207KeyStore keyStore = KeyStore.getInstance(keyStoreType);
208keyStore.load(null, null);
209keyStore.setCertificateEntry("ca", ca);
210
211// Create a TrustManager that trusts the CAs in our KeyStore
212String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
213TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
214tmf.init(keyStore);
215
216// Create an SSLContext that uses our TrustManager
217SSLContext context = SSLContext.getInstance("TLS");
218context.init(null, tmf.getTrustManagers(), null);
219
220// Tell the URLConnection to use a SocketFactory from our SSLContext
221URL url = new URL("https://certs.cac.washington.edu/CAtest/");
222HttpsURLConnection urlConnection =
223    (HttpsURLConnection)url.openConnection();
224urlConnection.setSSLSocketFactory(context.getSocketFactory());
225InputStream in = urlConnection.getInputStream();
226copyInputStreamToOutputStream(in, System.out);
227</pre>
228
229<p>With a custom {@link javax.net.ssl.TrustManager} that knows about your CAs,
230the system is able to validate
231that your server certificate come from a trusted issuer.</p>
232
233<p class="caution"><strong>Caution:</strong>
234Many web sites describe a poor alternative solution which is to install a
235{@link javax.net.ssl.TrustManager} that does nothing. If you do this you might as well not
236be encrypting your communication, because anyone can attack your users at a public Wi-Fi hotspot
237by using <acronym title="Domain Name System">DNS</acronym> tricks to send your users'
238traffic through a proxy of their own that pretends to be your server. The attacker can then
239record passwords and other personal data. This works because the attacker can generate a
240certificate and&mdash;without a {@link javax.net.ssl.TrustManager} that actually
241validates that the certificate comes from a trusted
242source&mdash;your app could be talking to anyone. So don't do this, not even temporarily. You can
243always make your app trust the issuer of the server's certificate, so just do it.</p>
244
245
246
247<h3 id="SelfSigned">Self-signed server certificate</h3>
248
249<p>The second case of {@link javax.net.ssl.SSLHandshakeException} is
250due to a self-signed certificate, which means the server is behaving as its own CA.
251This is similar to an unknown certificate authority, so you can use the
252same approach from the previous section.</p>
253
254<p>You can create your own {@link javax.net.ssl.TrustManager},
255this time trusting the server certificate directly. This has all of the
256downsides discussed earlier of tying your app directly to a certificate, but can be done
257securely. However, you should be careful to make sure your self-signed certificate has a
258reasonably strong key. As of 2012, a 2048-bit RSA signature with an exponent of 65537 expiring
259yearly is acceptable. When rotating keys, you should check for <a
260href="http://csrc.nist.gov/groups/ST/key_mgmt/index.html">recommendations</a> from an
261authority (such as <a href="http://www.nist.gov/">NIST</a>) about what is acceptable.</p>
262
263
264
265<h3 id="MissingCa">Missing intermediate certificate authority</h3>
266
267<p>The third case of {@link javax.net.ssl.SSLHandshakeException}
268occurs due to a missing intermediate CA. Most public
269CAs don't sign server certificates directly. Instead, they use their main CA certificate,
270referred to as the root CA, to sign intermediate CAs. They do this so the root CA can be stored
271offline to reduce risk of compromise. However, operating systems like Android typically
272trust only root CAs directly, which leaves a short gap of trust between the server
273certificate&mdash;signed by the intermediate CA&mdash;and the certificate verifier,
274which knows the root CA. To solve
275this, the server doesn't send the client only it's certificate during the SSL handshake, but
276a chain of certificates from the server CA through any intermediates necessary to reach a
277trusted root CA.</p>
278
279<p>To see what this looks like in practice, here's the <em>mail.google.com</em> certificate
280chain as viewed by the <a href="http://www.openssl.org/docs/apps/openssl.html">{@code openssl}</a>
281{@code s_client} command:</p>
282
283<pre class="no-pretty-print">
284$ openssl s_client -connect mail.google.com:443
285---
286Certificate chain
287 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=mail.google.com
288   i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
289 1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
290   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
291---
292</pre>
293
294
295<p>This shows that the server sends a certificate for <em>mail.google.com</em>
296issued by the <em>Thawte SGC</em> CA, which is an intermediate CA, and a second certificate
297for the <em>Thawte SGC</em> CA issued by a <em>Verisign</em> CA, which is the primary CA that's
298trusted by Android.</p>
299
300<p>However, it is not uncommon to configure a server to not include the necessary
301intermediate CA. For example, here is a server that can cause an error in Android browsers and
302exceptions in Android apps:</p>
303
304<pre class="no-pretty-print">
305$ openssl s_client -connect egov.uscis.gov:443
306---
307Certificate chain
308 0 s:/C=US/ST=District Of Columbia/L=Washington/O=U.S. Department of Homeland Security/OU=United States Citizenship and Immigration Services/OU=Terms of use at www.verisign.com/rpa (c)05/CN=egov.uscis.gov
309   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3
310---
311</pre>
312
313<p>What is interesting to note here is that visiting this server in most desktop browsers
314does not cause an error like a completely unknown CA or self-signed server certificate would
315cause. This is because most desktop browsers cache trusted intermediate CAs over time. Once
316a browser has visited and learned about an intermediate CA from one site, it won't
317need to have the intermediate CA included in the certificate chain the next time.</p>
318
319<p>Some sites do this intentionally for secondary web servers used to serve resources. For
320example, they might have their main HTML page served by a server with a full certificate
321chain, but have servers for resources such as images, CSS, or JavaScript not include the
322CA, presumably to save bandwidth. Unfortunately, sometimes these servers might be providing
323a web service you are trying to call from your Android app, which is not as forgiving.</p>
324
325<p>There are two approaches to solve this issue:</p>
326<ul>
327  <li>Configure the server to
328  include the intermediate CA in the server chain. Most CAs provide documentation on how to do
329  this for all common web servers. This is the only approach if you need the site to work with
330  default Android browsers at least through Android 4.2.</li>
331  <li>Or, treat the
332  intermediate CA like any other unknown CA, and create a {@link javax.net.ssl.TrustManager}
333  to trust it directly, as done in the previous two sections.</li>
334</ul>
335
336
337<h2 id="CommonHostnameProbs">Common Problems with Hostname Verification</h2>
338
339<p>As mentioned at the beginning of this article,
340there are two key parts to verifying an SSL connection. The first
341is to verify the certificate is from a trusted source, which was the focus of the previous
342section. The focus of this section is the second part: making sure the server you are
343talking to presents the right certificate. When it doesn't, you'll typically see an error
344like this:</p>
345
346<pre class="no-pretty-print">
347java.io.IOException: Hostname 'example.com' was not verified
348        at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223)
349        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446)
350        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
351        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
352        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
353        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
354        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
355</pre>
356
357
358<p>One reason this can happen is due to a server configuration error. The server is
359configured with a certificate that does not have a subject or subject alternative name fields
360that match the server you are trying to reach. It is possible to have one certificate be used
361with many different servers. For example, looking at the <em>google.com</em> certificate with
362<a href="http://www.openssl.org/docs/apps/openssl.html">{@code openssl}</a> {@code
363s_client -connect google.com:443 | openssl x509 -text} you can see that a subject
364that supports <em>*.google.com</em> but also subject alternative names for <em>*.youtube.com</em>,
365<em>*.android.com</em>, and others. The error occurs only when the server name you
366are connecting to isn't listed by the certificate as acceptable.</p>
367
368<p>Unfortunately this can happen for another reason as well: <a
369href="http://en.wikipedia.org/wiki/Virtual_hosting">virtual hosting</a>. When sharing a
370server for more than one hostname with HTTP, the web server can tell from the HTTP/1.1 request
371which target hostname the client is looking for. Unfortunately this is complicated with
372HTTPS, because the server has to know which certificate to return before it sees the HTTP
373request. To address this problem, newer versions of SSL, specifically TLSv.1.0 and later,
374support <a href="http://en.wikipedia.org/wiki/Server_Name_Indication">Server Name Indication
375(SNI)</a>, which allows the SSL client to specify the intended
376hostname to the server so the proper certificate can be returned.</p>
377
378<p>Fortunately, {@link javax.net.ssl.HttpsURLConnection} supports
379SNI since Android 2.3. Unfortunately, Apache
380HTTP Client does not, which is one of the many reasons we discourage its use. One workaround
381if you need to support Android 2.2 (and older) or Apache HTTP Client is to set up an alternative
382virtual host on a unique port so that it's unambiguous which server certificate to return.</p>
383
384<p>The more drastic alternative is to replace {@link javax.net.ssl.HostnameVerifier}
385with one that uses not the
386hostname of your virtual host, but the one returned by the server by default.</p>
387
388<p class="caution"><strong>Caution:</strong> Replacing {@link javax.net.ssl.HostnameVerifier}
389can be <strong>very dangerous</strong> if the other virtual host is
390not under your control, because a man-in-the-middle attack could direct traffic to another
391server without your knowledge.</p>
392
393<p>If you are still sure you want to override hostname verification, here is an example
394that replaces the verifier for a single {@link java.net.URLConnection}
395with one that still verifies that the hostname is at least on expected by the app:</p>
396
397<pre>
398// Create an HostnameVerifier that hardwires the expected hostname.
399// Note that is different than the URL's hostname:
400// example.com versus example.org
401HostnameVerifier hostnameVerifier = new HostnameVerifier() {
402    &#64;Override
403    public boolean verify(String hostname, SSLSession session) {
404        HostnameVerifier hv =
405            HttpsURLConnection.getDefaultHostnameVerifier();
406        return hv.verify("example.com", session);
407    }
408};
409
410// Tell the URLConnection to use our HostnameVerifier
411URL url = new URL("https://example.org/");
412HttpsURLConnection urlConnection =
413    (HttpsURLConnection)url.openConnection();
414urlConnection.setHostnameVerifier(hostnameVerifier);
415InputStream in = urlConnection.getInputStream();
416copyInputStreamToOutputStream(in, System.out);
417</pre>
418
419<p>But remember, if you find yourself replacing hostname verification, especially
420due to virtual hosting, it's still <strong>very dangerous</strong> if the other virtual host is
421not under your control and you should find an alternative hosting arrangement
422that avoids this issue.</p>
423
424
425
426
427<h2 id="WarningsSslSocket">Warnings About Using SSLSocket Directly</h2>
428
429<p>So far, the examples have focused on HTTPS using {@link javax.net.ssl.HttpsURLConnection}.
430Sometimes apps need to use SSL separate from HTTP. For example, an email app might use SSL variants
431of SMTP, POP3, or IMAP. In those cases, the app would want to use {@link javax.net.ssl.SSLSocket}
432directly, much the same way that {@link javax.net.ssl.HttpsURLConnection} does internally.</p>
433
434<p>The techniques described so
435far to deal with certificate verification issues also apply to {@link javax.net.ssl.SSLSocket}.
436In fact, when using a custom {@link javax.net.ssl.TrustManager}, what is passed to
437{@link javax.net.ssl.HttpsURLConnection} is an {@link javax.net.ssl.SSLSocketFactory}.
438So if you need to use a custom {@link javax.net.ssl.TrustManager} with an
439{@link javax.net.ssl.SSLSocket}, follow
440the same steps and use that {@link javax.net.ssl.SSLSocketFactory} to create your
441{@link javax.net.ssl.SSLSocket}.</p>
442
443<p class="caution"><strong>Caution:</strong>
444{@link javax.net.ssl.SSLSocket} <strong>does not</strong> perform hostname verification. It is
445up the your app to do its own hostname verification, preferably by calling {@link
446javax.net.ssl.HttpsURLConnection#getDefaultHostnameVerifier()} with the expected hostname. Further
447beware that {@link javax.net.ssl.HostnameVerifier#verify HostnameVerifier.verify()}
448doesn't throw an exception on error but instead returns a boolean result that you must
449explicitly check.</p>
450
451<p>Here is an example showing how you can do this. It shows that when connecting to
452<em>gmail.com</em> port 443 without SNI support, you'll receive a certificate for
453<em>mail.google.com</em>. This is expected in this case, so check to make sure that
454the certificate is indeed for <em>mail.google.com</em>:</p>
455
456<pre>
457// Open SSLSocket directly to gmail.com
458SocketFactory sf = SSLSocketFactory.getDefault();
459SSLSocket socket = (SSLSocket) sf.createSocket("gmail.com", 443);
460HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
461SSLSession s = socket.getSession();
462
463// Verify that the certicate hostname is for mail.google.com
464// This is due to lack of SNI support in the current SSLSocket.
465if (!hv.verify("mail.google.com", s)) {
466    throw new SSLHandshakeException("Expected mail.google.com, "
467                                    "found " + s.getPeerPrincipal());
468}
469
470// At this point SSLSocket performed certificate verificaiton and
471// we have performed hostname verification, so it is safe to proceed.
472
473// ... use socket ...
474socket.close();
475</pre>
476
477
478
479<h2 id="Blacklisting">Blacklisting</h2>
480
481<p>SSL relies heavily on CAs to issue certificates to only the properly verified owners
482of servers and domains. In rare cases, CAs are either tricked or, in the case of <a
483href="http://en.wikipedia.org/wiki/Comodo_Group#Breach_of_security">Comodo</a> or <a
484href="http://en.wikipedia.org/wiki/DigiNotar">DigiNotar</a>, breached,
485resulting in the certificates for a hostname to be issued to
486someone other than the owner of the server or domain.</p>
487
488<p>In order to mitigate this risk, Android has the ability to blacklist certain certificates or even
489whole CAs. While this list was historically built into the operating system, starting in
490Android 4.2 this list can be remotely updated to deal with future compromises.</p>
491
492
493
494<h2 id="Pinning">Pinning</h2>
495
496<p>An app can further protect itself from fraudulently issued certificates by a
497technique known as pinning. This is basically using the example provided in the unknown CA case
498above to restrict an app's trusted CAs to a small set known to be used by the app's servers. This
499prevents the compromise of one of the other 100+ CAs in the system from resulting in a breach of
500the apps secure channel.</p>
501
502
503
504<h2 id="ClientCert">Client Certificates</h2>
505
506<p>This article has focused on the user of SSL to secure communications with servers. SSL also
507supports the notion of client certificates that allow the server to validate the identity of a
508client. While beyond the scope of this article, the techniques involved are similar to specifying
509a custom {@link javax.net.ssl.TrustManager}.
510See the discussion about creating a custom {@link javax.net.ssl.KeyManager} in the documentation for
511{@link javax.net.ssl.HttpsURLConnection}.</p>
512
513
514
515<h2 id="nogotofail">
516  Nogotofail: A Network Traffic Security Testing Tool
517</h2>
518
519<p>
520  Nogotofail is a tool gives you an easy way to confirm that your apps are safe
521  against known TLS/SSL vulnerabilities and misconfigurations. It's an
522  automated, powerful, and scalable tool for testing network security issues on
523  any device whose network traffic could be made to go through it. </p>
524
525  <p>Nogotofail is useful for three main use cases:
526</p>
527
528<ul>
529  <li>Finding bugs and vulnerabilities.
530  </li>
531
532  <li>Verifying fixes and watching for regressions.
533  </li>
534
535  <li>Understanding what applications and devices are generating what traffic.
536  </li>
537</ul>
538
539<p>
540  Nogotofail works for Android, iOS, Linux, Windows, Chrome OS, OSX, in fact
541  any device you use to connect to the Internet. There’s an easy-to-use client
542  to configure the settings and get notifications on Android and Linux, as well
543  as the attack engine itself which can be deployed as a router, VPN server, or
544  proxy.
545</p>
546
547<p>
548  You can access the tool at the <a href=
549  "https://github.com/google/nogotofail">Nogotofail open source project</a>.
550</p>
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577