|
1 |
| -# Certificate Transparency for Android |
| 1 | +# Certificate Transparency for Android and Java |
2 | 2 |
|
3 |
| -[](https://github.com/babylonhealth/certificate-transparency-android/actions) |
4 |
| -[](https://codecov.io/gh/babylonhealth/certificate-transparency-android) |
5 |
| -[](https://bintray.com/babylonpartners/maven/certificatetransparency/_latestVersion) |
| 3 | +**This repository is no longer maintained, we cannot respond to issues |
| 4 | +or pull requests.** |
6 | 5 |
|
7 |
| -To protect our apps from man-in-the-middle attacks one of the first |
8 |
| -things that usually springs to mind is certificate pinning. However, the |
9 |
| -issues of certificate pinning are numerous. Firstly deciding on a |
10 |
| -reliable set of keys to pin against is tough. Once you made that |
11 |
| -decision if your expectations don't match reality your users suffer from |
12 |
| -not being able to access your app or website. Smashing Magazine learnt |
13 |
| -about this the hard way in late 2016 when they blocked users access for |
14 |
| -up to a year because of a mismatch between the pins and the |
15 |
| -certificates. On mobile fixing an invalid pin means pushing out a new |
16 |
| -version of an app which can still take a while to reach every user. |
| 6 | +While we can’t officially endorse software we don’t write ourselves, the |
| 7 | +original maintainers are maintaining a fork of this project under |
| 8 | +[https://github.com/appmattus/certificatetransparency](https://github.com/appmattus/certificatetransparency). |
17 | 9 |
|
18 |
| -So with certificate pinning falling out of favour, what should you do? |
19 |
| -The new kid in town is **certificate transparency**. |
20 |
| - |
21 |
| -## What is Certificate Transparency |
22 |
| - |
23 |
| -> Certificate Transparency helps eliminate these flaws by providing an |
24 |
| -open framework for monitoring and auditing SSL certificates in nearly |
25 |
| -real time. Specifically, Certificate Transparency makes it possible to |
26 |
| -detect SSL certificates that have been mistakenly issued by a |
27 |
| -certificate authority or maliciously acquired from an otherwise |
28 |
| -unimpeachable certificate authority. It also makes it possible to |
29 |
| -identify certificate authorities that have gone rogue and are |
30 |
| -maliciously issuing certificates. [https://www.certificate-transparency.org](https://www.certificate-transparency.org) |
31 |
| - |
32 |
| -Certificate transparency works by having a network of publicly |
33 |
| -accessible log servers that provide cryptographic evidence when a |
34 |
| -certificate authority issues new certificates for any domain. These log |
35 |
| -servers can then be monitored to look out for suspicious certificates as |
36 |
| -well as audited to prove the logs are working as expected. |
37 |
| - |
38 |
| -These log servers help achieve the three main goals: |
39 |
| - |
40 |
| -- Make it hard to issue certificates without the domain owners knowledge |
41 |
| -- Provide auditing and monitoring to spot mis-issued certificates |
42 |
| -- Protect users from mis-issued certificates |
43 |
| - |
44 |
| -When you submit a certificate to a log server, the server responds with |
45 |
| -a signed certificate timestamp (SCT), which is a promise that the |
46 |
| -certificate will be added to the logs within 24 hours (the maximum merge |
47 |
| -delay). User agents, such as web browsers and mobile apps, use this SCT |
48 |
| -to verify the validity of a domain. |
49 |
| - |
50 |
| -For a more detailed overview of certificate transparency, please watch |
51 |
| -the excellent video |
52 |
| -[The Very Best of Certificate Transparency (2011-)](https://www.facebook.com/atscaleevents/videos/1904853043121124/) |
53 |
| -from Networking @Scale 2017. |
54 |
| - |
55 |
| -More details about how the verification works in the library can be |
56 |
| -found at [Android Security: Certificate Transparency](https://medium.com/@appmattus/android-security-certificate-transparency-601c18157c44) |
57 |
| - |
58 |
| -## Security |
59 |
| - |
60 |
| -We are open about the security of our library and provide a threat model in the |
61 |
| -[source code](ThreatDragonModels/), created using |
62 |
| -[OWASP Threat Dragon](https://threatdragon.org). If you feel there is something |
63 |
| -we have missed please reach out so we can keep this up to date. |
64 |
| - |
65 |
| -## Getting started |
66 |
| - |
67 |
| -[](https://bintray.com/babylonpartners/maven/certificatetransparency/_latestVersion) |
68 |
| - |
69 |
| -For Android modules include the `android` dependency in your |
70 |
| -build.gradle file which ensures the necessary ProGuard rules are |
71 |
| -present: |
72 |
| - |
73 |
| -```groovy |
74 |
| -implementation 'com.babylon.certificatetransparency:certificatetransparency-android:<latest-version>' |
75 |
| -``` |
76 |
| - |
77 |
| -For Java library modules include the dependency as follows: |
78 |
| - |
79 |
| -```groovy |
80 |
| -implementation 'com.babylon.certificatetransparency:certificatetransparency:<latest-version>' |
81 |
| -``` |
82 |
| - |
83 |
| -### OkHttp |
84 |
| - |
85 |
| -The library allows you to create a network interceptor for use with |
86 |
| -OkHttp where you specify which hosts to perform certificate transparency |
87 |
| -checks on. Wildcards are accepted but note that *.babylonhealth.com will |
88 |
| -match any sub-domain but not "babylonhealth.com" with no subdomain. |
89 |
| - |
90 |
| -```kotlin |
91 |
| -val interceptor = certificateTransparencyInterceptor { |
92 |
| - // Enable for the provided hosts |
93 |
| - +"*.babylonhealth.com" |
94 |
| - |
95 |
| - // Exclude specific hosts |
96 |
| - -"legacy.babylonhealth.com" |
97 |
| -} |
98 |
| - |
99 |
| -val client = OkHttpClient.Builder().apply { |
100 |
| - addNetworkInterceptor(interceptor) |
101 |
| -}.build() |
102 |
| -``` |
103 |
| - |
104 |
| -You can also enable certificate transparency for all hosts with `*.*`: |
105 |
| - |
106 |
| -```kotlin |
107 |
| -val interceptor = certificateTransparencyInterceptor { |
108 |
| - // Enable for all hosts |
109 |
| - +"*.*" |
110 |
| - |
111 |
| - // Exclude specific hosts as necessary |
112 |
| - -"legacy.babylonhealth.com" |
113 |
| -} |
114 |
| -``` |
115 |
| - |
116 |
| -In Java, you can create the network interceptor through |
117 |
| -[CTInterceptorBuilder](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/CTInterceptorBuilder.kt). |
118 |
| - |
119 |
| -### Retrofit |
120 |
| - |
121 |
| -With Retrofit built on top of OkHttp, configuring it for certificate |
122 |
| -transparency is as simple as setting up an OkHttpClient as shown above |
123 |
| -and supplying that to your Retrofit.Builder. |
124 |
| - |
125 |
| -```kotlin |
126 |
| -val retrofit = Retrofit.Builder() |
127 |
| - .baseUrl("https://babylonhealth.com") |
128 |
| - .addConverterFactory(GsonConverterFactory.create()) |
129 |
| - .client(okHttpClient) |
130 |
| - .build() |
131 |
| -``` |
132 |
| - |
133 |
| -### HttpURLConnection |
134 |
| - |
135 |
| -Firstly if you are still using HttpURLConnection consider upgrading to |
136 |
| -OkHttp. The version built into Android, naturally, is a fixed version so |
137 |
| -you won't get any security updates or bug fixes. |
138 |
| - |
139 |
| -To use with HttpURLConnection you wrap the original hostname verifier |
140 |
| -before calling connect() on the connection: |
141 |
| - |
142 |
| -```kotlin |
143 |
| -val connection = URL("https://www.babylonhealth.com").openConnection() |
144 |
| -if (connection is HttpsURLConnection) { |
145 |
| - connection.hostnameVerifier = certificateTransparencyHostnameVerifier(connection.hostnameVerifier) { |
146 |
| - // Enable for the provided hosts |
147 |
| - +"*.babylonhealth.com" |
148 |
| - |
149 |
| - // Exclude specific hosts |
150 |
| - -"legacy.babylonhealth.com" |
151 |
| - } |
152 |
| -} |
153 |
| -``` |
154 |
| - |
155 |
| -In Java, you can create the hostname verifier through |
156 |
| -[CTHostnameVerifierBuilder](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/CTHostnameVerifierBuilder.kt). |
157 |
| - |
158 |
| -### Volley |
159 |
| - |
160 |
| -Overriding the *HostnameVerifier* can be achieved by overriding |
161 |
| -`createConnection` when creating the `RequestQueue`: |
162 |
| - |
163 |
| -```kotlin |
164 |
| -val requestQueue = Volley.newRequestQueue(applicationContext, object : HurlStack() { |
165 |
| - override fun createConnection(url: URL): HttpURLConnection { |
166 |
| - val connection = super.createConnection(url) |
167 |
| - if (connection is HttpsURLConnection) { |
168 |
| - connection.hostnameVerifier = certificateTransparencyHostnameVerifier(connection.hostnameVerifier) { |
169 |
| - // Enable for the provided hosts |
170 |
| - +"*.babylonhealth.com" |
171 |
| - |
172 |
| - // Exclude specific hosts |
173 |
| - -"legacy.babylonhealth.com" |
174 |
| - } |
175 |
| - } |
176 |
| - return connection |
177 |
| - } |
178 |
| -}) |
179 |
| -``` |
180 |
| - |
181 |
| -### Apache HttpClient |
182 |
| - |
183 |
| -Currently, there is no support in the library for Apache HttpClient. |
184 |
| -However, adding the functionality would be relatively easy to add if |
185 |
| -there is enough demand. |
186 |
| - |
187 |
| -### WebViews |
188 |
| - |
189 |
| -With WebViews on Android now being provided by Chrome, hopefully in the |
190 |
| -long-term certificate transparency support will come for free. There is |
191 |
| -a proposal to add an [Expect-CT](https://datatracker.ietf.org/doc/draft-stark-expect-ct/) |
192 |
| -header to instruct user agents to expect valid SCTs which would help |
193 |
| -enforce this. |
194 |
| - |
195 |
| -Assuming that never happens, WebViews are tricky, not least because |
196 |
| -there is no perfect way to implement certificate transparency in them. |
197 |
| -The best you can do is override *shouldInterceptRequest* and implement |
198 |
| -the network calls yourself using one of the above methods. However, you |
199 |
| -can only intercept GET requests so if your WebViews use POST requests |
200 |
| -then you are out of luck. |
201 |
| - |
202 |
| -## Advanced configuration |
203 |
| - |
204 |
| -### Network Interceptor |
205 |
| - |
206 |
| -The network interceptor allows you to configure the following |
207 |
| -properties: |
208 |
| - |
209 |
| -**Trust Manager** [X509TrustManager](https://docs.oracle.com/javase/6/docs/api/javax/net/ssl/X509TrustManager.html) |
210 |
| -used to clean the certificate chain |
211 |
| -*Default:* Platform default [X509TrustManager](https://docs.oracle.com/javase/6/docs/api/javax/net/ssl/X509TrustManager.html) |
212 |
| -created through [TrustManagerFactory](http://docs.oracle.com/javase/6/docs/api/javax/net/ssl/TrustManagerFactory.html) |
213 |
| - |
214 |
| -**Log List Data Source** A [DataSource](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/datasource/DataSource.kt) |
215 |
| -providing a list of [LogServer](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/loglist/LogServer.kt) |
216 |
| -*Default:* In memory cached log list loaded from [https://www.gstatic.com/ct/log_list/log_list.json](https://www.gstatic.com/ct/log_list/log_list.json) |
217 |
| - |
218 |
| -**Policy** [CTPolicy](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/CTPolicy.kt) |
219 |
| -which will verify correct number of SCTs are present |
220 |
| -*Default:* Policy which follows rules of [Chromium CT Policy](https://github.com/chromium/ct-policy/blob/master/ct_policy.md) |
221 |
| - |
222 |
| -**Fail On Error** Determine if a failure to pass certificate |
223 |
| -transparency results in the connection being closed. A value of `true` |
224 |
| -ensures the connection is closed on errors |
225 |
| -*Default:* true |
226 |
| - |
227 |
| -**Logger** [CTLogger](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/CTLogger.kt) |
228 |
| -which will be called with all results. |
229 |
| -On Android you can use the provided [BasicAndroidCTLogger](./certificatetransparency-android/src/main/kotlin/com/babylon/certificatetransparency/BasicAndroidCTLogger.kt) |
230 |
| -which logs with the tag `CertificateTransparency` by setting |
231 |
| -`logger = BasicAndroidCRLogger(BuildConfig.DEBUG)` using your apps |
232 |
| -`BuildConfig`. |
233 |
| -*Default:* none |
234 |
| - |
235 |
| -**Hosts** Verify certificate transparency for hosts that match a |
236 |
| -pattern which is a lower-case host name or wildcard pattern such as |
237 |
| -`*.example.com`. |
238 |
| - |
239 |
| -**Certificate Chain Provider Factory** Provide a custom implementation |
240 |
| -of a certificate chain cleaner. |
241 |
| -*Default:* Platform default factory which resolves to [AndroidCertificateChainCleaner](./certificatetransparency-android/src/main/kotlin/com/babylon/certificatetransparency/chaincleaner/AndroidCertificateChainCleaner.kt) |
242 |
| -or [BasicCertificateChainCleaner](./certificatetransparency/src/main/kotlin/com/babylon/certificatetransparency/chaincleaner/BasicCertificateChainCleaner.kt). |
243 |
| - |
244 |
| -### HostnameVerifier |
245 |
| - |
246 |
| -In addition to all of the properties above the hostname verifier ensures |
247 |
| -you provide a **delegate** hostname verifier which is used to first |
248 |
| -verify the hostname before the certificate transparency checks occur. |
249 |
| - |
250 |
| -## Contributing |
251 |
| - |
252 |
| -Please read [CONTRIBUTING.md](CONTRIBUTING.md) |
253 |
| -for details on our code of conduct, and the process for submitting pull |
254 |
| -requests to us. |
255 |
| - |
256 |
| -## Versioning |
257 |
| - |
258 |
| -We use [SemVer](http://semver.org/) for versioning. For the versions |
259 |
| -available, see the [tags on this repository](https://github.com/babylonhealth/certificate-transparency-android/tags). |
260 |
| - |
261 |
| -## License |
262 |
| - |
263 |
| -[](LICENSE.md) |
264 |
| - |
265 |
| -This project is licensed under the Apache License, Version 2.0 - see the |
266 |
| -[LICENSE.md](LICENSE.md) file for details |
| 10 | +You can find the original README [here](readme-old.md) |
0 commit comments