From fc5255ce56624dcc60dd7092515312cc17d09691 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 6 Nov 2024 14:52:47 +0530 Subject: [PATCH] CertUtil: Move certificate pinning logic to okhttpclientmodule Signed-off-by: Aayush Gupta --- .../store/data/network/OkHttpClientModule.kt | 42 ++++++++++++++++++- .../java/com/aurora/store/util/CertUtil.kt | 35 ---------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/aurora/store/data/network/OkHttpClientModule.kt b/app/src/main/java/com/aurora/store/data/network/OkHttpClientModule.kt index 0edda0ed3..a04e93312 100644 --- a/app/src/main/java/com/aurora/store/data/network/OkHttpClientModule.kt +++ b/app/src/main/java/com/aurora/store/data/network/OkHttpClientModule.kt @@ -20,9 +20,11 @@ package com.aurora.store.data.network import android.content.Context +import android.util.Base64 import android.util.Log +import com.aurora.store.R +import com.aurora.store.data.model.Algorithm import com.aurora.store.data.model.ProxyInfo -import com.aurora.store.util.CertUtil import com.aurora.store.util.Preferences import com.aurora.store.util.Preferences.PREFERENCE_PROXY_ENABLED import com.aurora.store.util.Preferences.PREFERENCE_PROXY_INFO @@ -32,12 +34,17 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import java.io.ByteArrayInputStream +import java.io.InputStream import okhttp3.CertificatePinner import okhttp3.OkHttpClient import java.net.Authenticator import java.net.InetSocketAddress import java.net.PasswordAuthentication import java.net.Proxy +import java.security.MessageDigest +import java.security.cert.CertificateFactory +import java.security.cert.X509Certificate import java.util.concurrent.TimeUnit import javax.inject.Singleton @@ -47,6 +54,9 @@ object OkHttpClientModule { private const val TAG = "HttpClient" + private const val CERT_BEGIN = "-----BEGIN CERTIFICATE-----" + private const val CERT_END = "-----END CERTIFICATE-----" + @Provides @Singleton fun providesOkHttpClientInstance(certPinner: CertificatePinner, proxy: Proxy?): OkHttpClient { @@ -66,7 +76,7 @@ object OkHttpClientModule { @Singleton fun providesCertificatePinnerInstance(@ApplicationContext context: Context): CertificatePinner { // Google needs special handling, see: https://pki.goog/faq/#faq-27 - val googleRootCerts = CertUtil.getGoogleRootCertHashes(context).map { "sha256/$it" } + val googleRootCerts = getGoogleRootCertHashes(context).map { "sha256/$it" } .toTypedArray() return CertificatePinner.Builder() @@ -108,4 +118,32 @@ object OkHttpClientModule { return null } } + + private fun getGoogleRootCertHashes(context: Context): List { + return try { + val certs = getX509Certificates(context.resources.openRawResource(R.raw.google_roots_ca)) + certs.map { + val messageDigest = MessageDigest.getInstance(Algorithm.SHA256.value) + messageDigest.update(it.publicKey.encoded) + Base64.encodeToString(messageDigest.digest(), Base64.NO_WRAP) + } + } catch (exception: Exception) { + Log.e(TAG, "Failed to get SHA256 certificate hash", exception) + emptyList() + } + } + + private fun getX509Certificates(inputStream: InputStream): List { + val certificateFactory = CertificateFactory.getInstance("X509") + val rawCerts = inputStream + .bufferedReader() + .use { it.readText() } + .split(CERT_END) + .map { it.substringAfter(CERT_BEGIN).substringBefore(CERT_END).replace("\n", "") } + .filterNot { it.isBlank() } + val decodedCerts = rawCerts.map { Base64.decode(it, Base64.DEFAULT) } + return decodedCerts.map { + certificateFactory.generateCertificate(ByteArrayInputStream(it)) as X509Certificate + } + } } diff --git a/app/src/main/java/com/aurora/store/util/CertUtil.kt b/app/src/main/java/com/aurora/store/util/CertUtil.kt index 2ec74ec5d..195d97fbf 100644 --- a/app/src/main/java/com/aurora/store/util/CertUtil.kt +++ b/app/src/main/java/com/aurora/store/util/CertUtil.kt @@ -27,22 +27,15 @@ import android.util.Log import com.aurora.extensions.generateX509Certificate import com.aurora.extensions.getInstallerPackageNameCompat import com.aurora.extensions.isPAndAbove -import com.aurora.store.R import com.aurora.store.data.model.Algorithm import com.aurora.store.util.PackageUtil.getPackageInfo -import java.io.ByteArrayInputStream -import java.io.InputStream import java.security.MessageDigest -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate object CertUtil { private val TAG = "CertUtil" - private const val CERT_BEGIN = "-----BEGIN CERTIFICATE-----" - private const val CERT_END = "-----END CERTIFICATE-----" - fun isFDroidApp(context: Context, packageName: String): Boolean { return isInstalledByFDroid(context, packageName) || isSignedByFDroid(context, packageName) } @@ -69,20 +62,6 @@ object CertUtil { } } - fun getGoogleRootCertHashes(context: Context): List { - return try { - val certs = getX509Certificates(context.resources.openRawResource(R.raw.google_roots_ca)) - certs.map { - val messageDigest = MessageDigest.getInstance(Algorithm.SHA256.value) - messageDigest.update(it.publicKey.encoded) - Base64.encodeToString(messageDigest.digest(), Base64.NO_WRAP) - } - } catch (exception: Exception) { - Log.e(TAG, "Failed to get SHA256 certificate hash", exception) - emptyList() - } - } - private fun isSignedByFDroid(context: Context, packageName: String): Boolean { return try { getX509Certificates(context, packageName).any { cert -> @@ -106,20 +85,6 @@ object CertUtil { ) } - private fun getX509Certificates(inputStream: InputStream): List { - val certificateFactory = CertificateFactory.getInstance("X509") - val rawCerts = inputStream - .bufferedReader() - .use { it.readText() } - .split(CERT_END) - .map { it.substringAfter(CERT_BEGIN).substringBefore(CERT_END).replace("\n", "") } - .filterNot { it.isBlank() } - val decodedCerts = rawCerts.map { Base64.decode(it, Base64.DEFAULT) } - return decodedCerts.map { - certificateFactory.generateCertificate(ByteArrayInputStream(it)) as X509Certificate - } - } - private fun getX509Certificates(context: Context, packageName: String): List { return try { val packageInfo = getPackageInfoWithSignature(context, packageName)