Skip to content

Commit 4b10918

Browse files
committed
Make the UI scrollable, and separate buttons more clearly by type
The types should correspond to pass states: in general, unpinned requests should succeed as long as you cover basic system certificate setup, pinned requests should succeed given a patch for that specific case (but each case is an off-the-shelf common example) and the last raw request is more-or-less impossible to handle generically and so required reverse engineering.
1 parent 8411df9 commit 4b10918

File tree

2 files changed

+143
-121
lines changed

2 files changed

+143
-121
lines changed

app/src/main/java/tech/httptoolkit/pinning_demo/MainActivity.kt

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,44 @@ class MainActivity : AppCompatActivity() {
165165
}
166166
}
167167

168+
// Manually pinned by building an SSLContext that trusts only the correct certificate, and then
169+
// connecting with the native HttpsUrlConnection API:
170+
fun sendContextPinned(view: View) {
171+
GlobalScope.launch(Dispatchers.IO) {
172+
onStart(R.id.context_pinned)
173+
174+
val cf = CertificateFactory.getInstance("X.509")
175+
val caStream = BufferedInputStream(resources.openRawResource(R.raw.lets_encrypt_isrg_root))
176+
val caCertificate = cf.generateCertificate(caStream)
177+
178+
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
179+
keyStore.load(null)
180+
keyStore.setCertificateEntry("ca", caCertificate)
181+
182+
val trustManagerFactory = TrustManagerFactory
183+
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
184+
trustManagerFactory.init(keyStore)
185+
186+
try {
187+
val context = SSLContext.getInstance("TLS")
188+
context.init(null, trustManagerFactory.trustManagers, null)
189+
190+
val mURL = URL("https://ecc384.badssl.com")
191+
with(mURL.openConnection() as HttpsURLConnection) {
192+
this.sslSocketFactory = context.socketFactory
193+
194+
println("URL: ${this.url}")
195+
println("Response Code: ${this.responseCode}")
196+
}
197+
198+
onSuccess(R.id.context_pinned)
199+
} catch (e: Throwable) {
200+
println(e)
201+
onError(R.id.context_pinned, e.toString())
202+
}
203+
}
204+
}
205+
168206
fun sendOkHttpPinned(view: View) {
169207
GlobalScope.launch(Dispatchers.IO) {
170208
onStart(R.id.okhttp_pinned)
@@ -391,44 +429,6 @@ class MainActivity : AppCompatActivity() {
391429
}
392430
}
393431

394-
// Manually pinned by building an SSLContext that trusts only the correct certificate, and then
395-
// connecting with the native HttpsUrlConnection API:
396-
fun sendCustomContextPinned(view: View) {
397-
GlobalScope.launch(Dispatchers.IO) {
398-
onStart(R.id.custom_context_pinned)
399-
400-
val cf = CertificateFactory.getInstance("X.509")
401-
val caStream = BufferedInputStream(resources.openRawResource(R.raw.lets_encrypt_isrg_root))
402-
val caCertificate = cf.generateCertificate(caStream)
403-
404-
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
405-
keyStore.load(null)
406-
keyStore.setCertificateEntry("ca", caCertificate)
407-
408-
val trustManagerFactory = TrustManagerFactory
409-
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
410-
trustManagerFactory.init(keyStore)
411-
412-
try {
413-
val context = SSLContext.getInstance("TLS")
414-
context.init(null, trustManagerFactory.trustManagers, null)
415-
416-
val mURL = URL("https://ecc384.badssl.com")
417-
with(mURL.openConnection() as HttpsURLConnection) {
418-
this.sslSocketFactory = context.socketFactory
419-
420-
println("URL: ${this.url}")
421-
println("Response Code: ${this.responseCode}")
422-
}
423-
424-
onSuccess(R.id.custom_context_pinned)
425-
} catch (e: Throwable) {
426-
println(e)
427-
onError(R.id.custom_context_pinned, e.toString())
428-
}
429-
}
430-
}
431-
432432
// Manually pinned at the lowest level: creating a raw TLS connection, disabling all checks,
433433
// and then directly analysing the certificate that's received after connection, before doing
434434
// HTTP by just writing & reading raw strings. Not a good idea, but the hardest to unpin!
Lines changed: 105 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,127 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
3+
<ScrollView
4+
xmlns:android="http://schemas.android.com/apk/res/android"
35
xmlns:app="http://schemas.android.com/apk/res-auto"
46
xmlns:tools="http://schemas.android.com/tools"
57
android:layout_width="match_parent"
68
android:layout_height="match_parent"
79
tools:context=".MainActivity">
810

9-
<LinearLayout
10-
android:id="@+id/linearLayout"
11-
android:layout_width="wrap_content"
12-
android:layout_height="wrap_content"
13-
android:orientation="vertical"
14-
app:layout_constraintBottom_toBottomOf="parent"
15-
app:layout_constraintEnd_toEndOf="parent"
16-
app:layout_constraintStart_toStartOf="parent"
17-
app:layout_constraintTop_toTopOf="parent">
18-
19-
<Button
20-
android:id="@+id/unpinned"
21-
android:layout_width="match_parent"
22-
android:layout_height="wrap_content"
23-
android:onClick="sendUnpinned"
24-
android:text="Unpinned request" />
11+
<androidx.constraintlayout.widget.ConstraintLayout
12+
android:layout_width="match_parent"
13+
android:layout_height="match_parent"
14+
android:padding="10dp">
2515

26-
<Button
27-
android:id="@+id/webview_unpinned"
16+
<LinearLayout
17+
android:id="@+id/linearLayout"
2818
android:layout_width="match_parent"
2919
android:layout_height="wrap_content"
30-
android:onClick="sendUnpinnedWebView"
31-
android:text="Unpinned WebView request" />
20+
android:orientation="vertical"
21+
app:layout_constraintBottom_toBottomOf="parent"
22+
app:layout_constraintEnd_toEndOf="parent"
23+
app:layout_constraintStart_toStartOf="parent"
24+
app:layout_constraintTop_toTopOf="parent">
3225

33-
<Button
34-
android:id="@+id/config_pinned"
35-
android:layout_width="match_parent"
36-
android:layout_height="wrap_content"
37-
android:onClick="sendConfigPinned"
38-
android:text="Config-pinned request" />
26+
<Button
27+
android:id="@+id/unpinned"
28+
android:layout_width="match_parent"
29+
android:layout_height="wrap_content"
30+
android:onClick="sendUnpinned"
31+
android:text="Unpinned request" />
3932

40-
<Button
41-
android:id="@+id/okhttp_pinned"
42-
android:layout_width="match_parent"
43-
android:layout_height="wrap_content"
44-
android:onClick="sendOkHttpPinned"
45-
android:text="OkHTTP pinned request" />
33+
<Button
34+
android:id="@+id/webview_unpinned"
35+
android:layout_width="match_parent"
36+
android:layout_height="wrap_content"
37+
android:onClick="sendUnpinnedWebView"
38+
android:text="Unpinned WebView request" />
4639

47-
<Button
48-
android:id="@+id/volley_pinned"
49-
android:layout_width="match_parent"
50-
android:layout_height="wrap_content"
51-
android:onClick="sendVolleyPinned"
52-
android:text="Volley pinned request" />
40+
<View
41+
android:layout_width="match_parent"
42+
android:layout_height="1dp"
43+
android:layout_marginTop="10dp"
44+
android:layout_marginBottom="10dp"
45+
android:background="@android:color/darker_gray"/>
5346

54-
<Button
55-
android:id="@+id/trustkit_pinned"
56-
android:layout_width="match_parent"
57-
android:layout_height="wrap_content"
58-
android:onClick="sendTrustKitPinned"
59-
android:text="TrustKit pinned request" />
47+
<Button
48+
android:id="@+id/config_pinned"
49+
android:layout_width="match_parent"
50+
android:layout_height="wrap_content"
51+
android:onClick="sendConfigPinned"
52+
android:text="Config-pinned request" />
6053

61-
<Button
62-
android:id="@+id/appmattus_ct_checked"
63-
android:layout_width="match_parent"
64-
android:layout_height="wrap_content"
65-
android:onClick="sendAppmattusCTChecked"
66-
android:text="Appmattus CT request" />
54+
<Button
55+
android:id="@+id/context_pinned"
56+
android:layout_width="match_parent"
57+
android:layout_height="wrap_content"
58+
android:onClick="sendContextPinned"
59+
android:text="Context-pinned request" />
6760

68-
<Button
69-
android:id="@+id/appmattus_okhttp_ct_checked"
70-
android:layout_width="match_parent"
71-
android:layout_height="wrap_content"
72-
android:onClick="sendAppmattusOkHttpCTChecked"
73-
android:text="Appmattus+OkHttp CT request" />
61+
<Button
62+
android:id="@+id/okhttp_pinned"
63+
android:layout_width="match_parent"
64+
android:layout_height="wrap_content"
65+
android:onClick="sendOkHttpPinned"
66+
android:text="OkHTTP pinned request" />
7467

75-
<Button
76-
android:id="@+id/appmattus_raw_ct_checked"
77-
android:layout_width="match_parent"
78-
android:layout_height="wrap_content"
79-
android:onClick="sendAppmattusRawCTChecked"
80-
android:text="Appmattus+raw TLS CT" />
68+
<Button
69+
android:id="@+id/volley_pinned"
70+
android:layout_width="match_parent"
71+
android:layout_height="wrap_content"
72+
android:onClick="sendVolleyPinned"
73+
android:text="Volley pinned request" />
8174

82-
<Button
83-
android:id="@+id/appmattus_webview_ct_checked"
84-
android:layout_width="match_parent"
85-
android:layout_height="wrap_content"
86-
android:onClick="sendAppmattusCTWebView"
87-
android:text="Appmattus+WebView CT" />
75+
<Button
76+
android:id="@+id/trustkit_pinned"
77+
android:layout_width="match_parent"
78+
android:layout_height="wrap_content"
79+
android:onClick="sendTrustKitPinned"
80+
android:text="TrustKit pinned request" />
8881

89-
<Button
90-
android:id="@+id/custom_context_pinned"
91-
android:layout_width="match_parent"
92-
android:layout_height="wrap_content"
93-
android:onClick="sendCustomContextPinned"
94-
android:text="Custom context-pinned request" />
82+
<Button
83+
android:id="@+id/appmattus_ct_checked"
84+
android:layout_width="match_parent"
85+
android:layout_height="wrap_content"
86+
android:onClick="sendAppmattusCTChecked"
87+
android:text="Appmattus CT request" />
9588

96-
<Button
97-
android:id="@+id/custom_raw_socket_pinned"
98-
android:layout_width="match_parent"
99-
android:layout_height="wrap_content"
100-
android:onClick="sendCustomRawSocketPinned"
101-
android:text="Custom manually pinned raw request" />
89+
<Button
90+
android:id="@+id/appmattus_okhttp_ct_checked"
91+
android:layout_width="match_parent"
92+
android:layout_height="wrap_content"
93+
android:onClick="sendAppmattusOkHttpCTChecked"
94+
android:text="Appmattus+OkHttp CT request" />
95+
96+
<Button
97+
android:id="@+id/appmattus_raw_ct_checked"
98+
android:layout_width="match_parent"
99+
android:layout_height="wrap_content"
100+
android:onClick="sendAppmattusRawCTChecked"
101+
android:text="Appmattus+raw TLS CT" />
102+
103+
<Button
104+
android:id="@+id/appmattus_webview_ct_checked"
105+
android:layout_width="match_parent"
106+
android:layout_height="wrap_content"
107+
android:onClick="sendAppmattusCTWebView"
108+
android:text="Appmattus+WebView CT" />
109+
110+
<View
111+
android:layout_width="match_parent"
112+
android:layout_height="1dp"
113+
android:layout_marginTop="10dp"
114+
android:layout_marginBottom="10dp"
115+
android:background="@android:color/darker_gray"/>
116+
117+
<Button
118+
android:id="@+id/custom_raw_socket_pinned"
119+
android:layout_width="match_parent"
120+
android:layout_height="wrap_content"
121+
android:onClick="sendCustomRawSocketPinned"
122+
android:text="Raw custom-pinned request" />
102123

103-
</LinearLayout>
124+
</LinearLayout>
104125

105-
</androidx.constraintlayout.widget.ConstraintLayout>
126+
</androidx.constraintlayout.widget.ConstraintLayout>
127+
</ScrollView>

0 commit comments

Comments
 (0)