diff --git a/.idea/misc.xml b/.idea/misc.xml index 25577e6..4f34ae0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -12,7 +12,9 @@ + + diff --git a/app/build.gradle b/app/build.gradle index 094fc5e..dbc2a1a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,6 +55,14 @@ dependencies { implementation 'com.journeyapps:zxing-android-embedded:4.3.0' implementation 'com.github.eu-digital-green-certificates:dgca-app-core-android:e4ad73eef8' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.1' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0' + + implementation "com.squareup.retrofit2:retrofit:2.9.0" + implementation "com.squareup.okhttp3:okhttp-tls:4.9.3" + implementation "com.google.code.gson:gson:2.9.0" + implementation "com.squareup.retrofit2:converter-gson:2.9.0" + + testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10b3117..760411a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" package="org.communiquons.dccaggregator"> + + ) : ArrayAdapter(cxt, 0, list) { diff --git a/app/src/main/java/org/communiquons/dccaggregator/apis/BaseNetwork.kt b/app/src/main/java/org/communiquons/dccaggregator/apis/BaseNetwork.kt new file mode 100644 index 0000000..3f91137 --- /dev/null +++ b/app/src/main/java/org/communiquons/dccaggregator/apis/BaseNetwork.kt @@ -0,0 +1,55 @@ +package org.communiquons.dccaggregator.apis + +import android.content.Context +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.OkHttpClient +import okhttp3.tls.HandshakeCertificates +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.security.cert.CertificateFactory +import java.security.cert.X509Certificate +import java.util.concurrent.TimeUnit + +@Suppress("SameParameterValue") +private fun certificateFromString(context: Context, fileName: String): X509Certificate { + return CertificateFactory.getInstance("X.509").generateCertificate( + context.resources.openRawResource( + context.resources.getIdentifier( + fileName, + "raw", context.packageName + ) + ) + ) as X509Certificate +} + +private var defaultOkHTTPClient: OkHttpClient? = null + +fun initOkHTTP(context: Context) { + if(defaultOkHTTPClient == null) + defaultOkHTTPClient = getDefaultOKHttpClient(context) +} + +fun getDefaultOKHttpClient(context: Context): OkHttpClient { + return OkHttpClient.Builder().apply { + val certificates: HandshakeCertificates = HandshakeCertificates.Builder() + .addPlatformTrustedCertificates() + .addTrustedCertificate(certificateFromString(context, "internal_july_2017")) + .build() + sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager) + callTimeout(1L, TimeUnit.MINUTES) + connectTimeout(1L, TimeUnit.MINUTES) + readTimeout(1L, TimeUnit.MINUTES) + writeTimeout(1L, TimeUnit.MINUTES) + }.build() +} + +fun getRetrofitService( + baseUrl: String, + clazz: Class, +): T { + return Retrofit.Builder() + .baseUrl(baseUrl.toHttpUrl()) + .addConverterFactory(GsonConverterFactory.create()) + .client(defaultOkHTTPClient!!) + .build().create(clazz) +} \ No newline at end of file diff --git a/app/src/main/java/org/communiquons/dccaggregator/apis/TousAntiCovidAPI.kt b/app/src/main/java/org/communiquons/dccaggregator/apis/TousAntiCovidAPI.kt new file mode 100644 index 0000000..9e7af8d --- /dev/null +++ b/app/src/main/java/org/communiquons/dccaggregator/apis/TousAntiCovidAPI.kt @@ -0,0 +1,41 @@ +package org.communiquons.dccaggregator.apis + +import android.content.Context +import org.communiquons.dccaggregator.TAC_RES_BASE_URL +import retrofit2.Response +import retrofit2.http.GET + +class ConfigurationEntry( + val name: String, + val value: Any, +) + +class ConfigurationWrapper(val config: List) + +class ParsedConfig(val activityPassGenerationServerPublicKey: String) + +interface TousAntiCovidAPI { + @GET("Config/config.json") + suspend fun config(): Response +} + +class TousAntiCovidAPIClient { + + private val tacAPI by lazy { + getRetrofitService( + TAC_RES_BASE_URL, + TousAntiCovidAPI::class.java + ) + } + + suspend fun getConfig(): ParsedConfig { + val res = tacAPI.config() + if (!res.isSuccessful) + throw Exception("Request failed with status ${res.code()}\n${res.errorBody()}") + + return ParsedConfig( + activityPassGenerationServerPublicKey = res.body()!!.config + .find { it -> it.name == "app.activityPass.generationServerPublicKey" }!!.value as String + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/communiquons/dccaggregator/models/Certificate.kt b/app/src/main/java/org/communiquons/dccaggregator/data/Certificate.kt similarity index 98% rename from app/src/main/java/org/communiquons/dccaggregator/models/Certificate.kt rename to app/src/main/java/org/communiquons/dccaggregator/data/Certificate.kt index 55ff6af..645edc8 100644 --- a/app/src/main/java/org/communiquons/dccaggregator/models/Certificate.kt +++ b/app/src/main/java/org/communiquons/dccaggregator/data/Certificate.kt @@ -1,4 +1,4 @@ -package org.communiquons.dccaggregator.models +package org.communiquons.dccaggregator.data import android.content.Context import dgca.verifier.app.decoder.CertificateDecodingResult diff --git a/app/src/main/java/org/communiquons/dccaggregator/helper/CertificatesList.kt b/app/src/main/java/org/communiquons/dccaggregator/helper/CertificatesList.kt index 5bdec5c..5255ad3 100644 --- a/app/src/main/java/org/communiquons/dccaggregator/helper/CertificatesList.kt +++ b/app/src/main/java/org/communiquons/dccaggregator/helper/CertificatesList.kt @@ -3,7 +3,7 @@ package org.communiquons.dccaggregator.helper import android.content.Context import androidx.preference.PreferenceManager import org.communiquons.dccaggregator.PREF_CERTS_LIST -import org.communiquons.dccaggregator.models.Certificate +import org.communiquons.dccaggregator.data.Certificate class CertificatesList(context: Context) { private val prefsManager = PreferenceManager.getDefaultSharedPreferences(context) diff --git a/app/src/main/java/org/communiquons/dccaggregator/viewmodel/CertsManagerViewModel.kt b/app/src/main/java/org/communiquons/dccaggregator/viewmodel/CertsManagerViewModel.kt new file mode 100644 index 0000000..08710b0 --- /dev/null +++ b/app/src/main/java/org/communiquons/dccaggregator/viewmodel/CertsManagerViewModel.kt @@ -0,0 +1,35 @@ +package org.communiquons.dccaggregator.viewmodel + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.communiquons.dccaggregator.apis.TousAntiCovidAPIClient +import org.communiquons.dccaggregator.helper.CertificatesList +import java.lang.Exception + +class CertsManagerViewModel() : ViewModel() { + + lateinit var certsManager: CertificatesList + + fun requestCertificate(): Job { + return viewModelScope.launch(Dispatchers.IO) { + try { + return@launch withContext(Dispatchers.IO) { + // First, fetch current signing key + val config = TousAntiCovidAPIClient().getConfig() + Log.d("testpk", config.activityPassGenerationServerPublicKey) + } + } catch (e: Exception) { + e.printStackTrace() + // return false + } + + // return true + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml new file mode 100644 index 0000000..2501e9f --- /dev/null +++ b/app/src/main/res/drawable/ic_check.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/generating_dialog.xml b/app/src/main/res/layout/generating_dialog.xml new file mode 100644 index 0000000..931fc7c --- /dev/null +++ b/app/src/main/res/layout/generating_dialog.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/cert_manager_top_menu.xml b/app/src/main/res/menu/cert_manager_top_menu.xml new file mode 100644 index 0000000..a3dc358 --- /dev/null +++ b/app/src/main/res/menu/cert_manager_top_menu.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/cert_menu.xml b/app/src/main/res/menu/certificate_menu.xml similarity index 100% rename from app/src/main/res/menu/cert_menu.xml rename to app/src/main/res/menu/certificate_menu.xml diff --git a/app/src/main/res/raw/internal_july_2017.pem b/app/src/main/res/raw/internal_july_2017.pem new file mode 100644 index 0000000..ae156f7 --- /dev/null +++ b/app/src/main/res/raw/internal_july_2017.pem @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +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 +YfHRSwb9eV4oxZk= +-----END CERTIFICATE----- diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6e51981..d435f15 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,4 +22,6 @@ Remove certificate Do you really want to remove this certificate from the list? No + Generate certificate + Waiting for your certificate, please wait… \ No newline at end of file