Tuesday, April 20, 2021

Thread Switch Performance difference between Thread, ThreadPool, and Coroutine

TL;DR

Thread Switch Time

private fun multiThreadTest_coroutine() {
val start = System.currentTimeMillis()
GlobalScope.launch(Dispatchers.IO) {
Log.d("thread_perf", "Coroutine 1: ${System.currentTimeMillis() - start}")
GlobalScope.launch(Dispatchers.Main) {
Log.d("thread_perf", "Coroutine 2: ${System.currentTimeMillis() - start}")
GlobalScope.launch(Dispatchers.IO) {
Log.d("thread_perf", "Coroutine 3: ${System.currentTimeMillis() - start}")
GlobalScope.launch(Dispatchers.Main) {
Log.d("thread_perf", "Coroutine 4: ${System.currentTimeMillis() - start}")
GlobalScope.launch(Dispatchers.IO) {
Log.d("thread_perf", "Coroutine 5: ${System.currentTimeMillis() - start}")
GlobalScope.launch(Dispatchers.Main) {
Log.d("thread_perf", "Coroutine 6: ${System.currentTimeMillis() - start}")
}
}
}
}
}
}
}
FirstD/thread_perf: Coroutine 1: 32D/thread_perf: Coroutine 2: 40D/thread_perf: Coroutine 3: 41D/thread_perf: Coroutine 4: 42D/thread_perf: Coroutine 5: 42D/thread_perf: Coroutine 6: 43SecondD/thread_perf: Coroutine 1: 0D/thread_perf: Coroutine 2: 2D/thread_perf: Coroutine 3: 2D/thread_perf: Coroutine 4: 3D/thread_perf: Coroutine 5: 4D/thread_perf: Coroutine 6: 4ThirdD/thread_perf: Coroutine 1: 0D/thread_perf: Coroutine 2: 1D/thread_perf: Coroutine 3: 1D/thread_perf: Coroutine 4: 2D/thread_perf: Coroutine 5: 2D/thread_perf: Coroutine 6: 2
val EXECUTOR: Executor = Executors.newCachedThreadPool()

private fun multiThreadTest_threadPool() {
val start = System.currentTimeMillis()
EXECUTOR.execute {
Log.d("thread_perf", "ThreadPool 1: ${System.currentTimeMillis() - start}")
runOnUiThread {
Log.d("thread_perf", "ThreadPool 2: ${System.currentTimeMillis() - start}")
EXECUTOR.execute {
Log.d("thread_perf", "ThreadPool 3: ${System.currentTimeMillis() - start}")
runOnUiThread {
Log.d("thread_perf", "ThreadPool 4: ${System.currentTimeMillis() - start}")
EXECUTOR.execute {
Log.d("thread_perf", "ThreadPool 5: ${System.currentTimeMillis() - start}")
runOnUiThread {
Log.d("thread_perf", "ThreadPool 6: ${System.currentTimeMillis() - start}")
}
}
}
}
}
}
}
FirstD/thread_perf: ThreadPool 1: 2D/thread_perf: ThreadPool 2: 8D/thread_perf: ThreadPool 3: 9D/thread_perf: ThreadPool 4: 9D/thread_perf: ThreadPool 5: 12D/thread_perf: ThreadPool 6: 12SecondD/thread_perf: ThreadPool 1: 0D/thread_perf: ThreadPool 2: 8D/thread_perf: ThreadPool 3: 8D/thread_perf: ThreadPool 4: 9D/thread_perf: ThreadPool 5: 9D/thread_perf: ThreadPool 6: 9ThirdD/thread_perf: ThreadPool 1: 1D/thread_perf: ThreadPool 2: 14D/thread_perf: ThreadPool 3: 14D/thread_perf: ThreadPool 4: 15D/thread_perf: ThreadPool 5: 15D/thread_perf: ThreadPool 6: 15
private fun multiThreadTest_thread() {
val start = System.currentTimeMillis()
Thread {
Log.d("thread_perf", "Thread 1: ${System.currentTimeMillis() - start}")
runOnUiThread {
Log.d("thread_perf", "Thread 2: ${System.currentTimeMillis() - start}")
Thread {
Log.d("thread_perf", "Thread 3: ${System.currentTimeMillis() - start}")
runOnUiThread {
Log.d("thread_perf", "Thread 4: ${System.currentTimeMillis() - start}")
Thread {
Log.d("thread_perf", "Thread 5: ${System.currentTimeMillis() - start}")
runOnUiThread {
Log.d("thread_perf", "Thread 6: ${System.currentTimeMillis() - start}")
}
}
.start()
}
}
.start()
}
}
.start()
}
FirstD/thread_perf: Thread 1: 1D/thread_perf: Thread 2: 13D/thread_perf: Thread 3: 15D/thread_perf: Thread 4: 15D/thread_perf: Thread 5: 17D/thread_perf: Thread 6: 17SecondD/thread_perf: Thread 1: 1D/thread_perf: Thread 2: 9D/thread_perf: Thread 3: 11D/thread_perf: Thread 4: 11D/thread_perf: Thread 5: 12D/thread_perf: Thread 6: 13ThirdD/thread_perf: Thread 1: 1D/thread_perf: Thread 2: 14D/thread_perf: Thread 3: 15D/thread_perf: Thread 4: 15D/thread_perf: Thread 5: 16D/thread_perf: Thread 6: 17

Conclusion

Friday, April 16, 2021

Network Security for Android Developers (MitM attack & SSL Pinning)

 This is a summary of what I have been learning about Network Security from an Android developer perspective. How to enhance your mobile security.

Why is SSL/TLS required? What is a man-in-the-middle(MitM) attack?

  • See your auth token for any API calls you make to the server
  • Alter information so that you could send money to the wrong account (see above image)

SSL vs TLS

SSL was replaced by TLS. TLS is the superior version of SSL. Although SSL should no longer be used, the name is still widely being used.

SSL version updates

The SSL version has been updated from SSL 1.0, 2.0, 3.0 to TLS 1.0, 1.1, 1.2, 1.3. The security vulnerabilities continuously have been found and updates have been made.
GlobalSign warns to disable TLS 1.0 and below. There are more and more enforcements for payment services to use at least TLS 1.2. Stripe, for example, blocked below TLS1.2 as of June 13, 2018.

Headache of supporting minimum TLS version

So what’s the issue? Just use the highest TLS version. There’s an issue for older devices.

Minimum TLS versions

Refer following for TLS version support per Android version:

What happens during a TLS handshake?

Charles

SSL Pinning comes to rescue

By providing the “true” server public key information, you can restrict the application to only trust the provided public keys for certain domain names.

How to get the server’s SHA256 public key?

  1. Use https://github.com/scottyab/ssl-pin-generator to get the SSL pins.

How to enable SSL Pinning?

Enabling SSL Pinning using OkHttp is following:

val certificatePinner = CertificatePinner.Builder()
.add(
"www.example.com",
"sha256/ZC3lTYTDBJQVf1P2V7+fibTqbIsWNR/X7CWNVW+CEEA="
).build()
val okHttpClient = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()

For Android 7.0+

For Android 7.0+, you can add it to the networkSecurityConfig config file.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<pin-set>
<pin digest="SHA-256">ZC3lTYTDBJQVf1P2V7+fibTqbIsWNR/X7CWNVW+CEEA=</pin>
<pin digest="SHA-256">GUAL5bejH7czkXcAeJ0vCiRxwMnVBsDlBMBsFtfLF8A=</pin>
</pin-set>
</domain-config>
</network-security-config>

What is the expected result?

When the hacker tries the man-in-the-middle(MitM) attack, the application will result in SSL Pinning mismatch and throw an exception.

Certificate Expiry

Certificate expires. We don’t want older app versions to stop working because the server certificate is renewed. So you might want to avoid hardcoding the SSL pin inside the application code. Make it so that it dynamically downloads the SSL pin from the server.