Get server public key
This commit is contained in:
		
							
								
								
									
										2
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@@ -12,7 +12,9 @@
 | 
			
		||||
        <entry key="app/src/main/res/layout/content_certs.xml" value="0.29483695652173914" />
 | 
			
		||||
        <entry key="app/src/main/res/layout/fragment_first.xml" value="0.29483695652173914" />
 | 
			
		||||
        <entry key="app/src/main/res/layout/fragment_second.xml" value="0.29483695652173914" />
 | 
			
		||||
        <entry key="app/src/main/res/layout/generating_dialog.xml" value="0.20729166666666668" />
 | 
			
		||||
        <entry key="app/src/main/res/layout/qr_entry.xml" value="0.28125" />
 | 
			
		||||
        <entry key="app/src/main/res/menu/cert_manager_top_menu.xml" value="0.20729166666666668" />
 | 
			
		||||
        <entry key="app/src/main/res/menu/cert_menu.xml" value="0.3697916666666667" />
 | 
			
		||||
        <entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.3859375" />
 | 
			
		||||
      </map>
 | 
			
		||||
 
 | 
			
		||||
@@ -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'
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    package="org.communiquons.dccaggregator">
 | 
			
		||||
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET" />
 | 
			
		||||
 | 
			
		||||
    <application
 | 
			
		||||
        android:name=".DCCAggregator"
 | 
			
		||||
        android:allowBackup="false"
 | 
			
		||||
 
 | 
			
		||||
@@ -10,4 +10,8 @@ const val RESULT_TEST_NEGATIVE = "260415000"
 | 
			
		||||
const val RESULT_TEST_POSITIVE = "260373001"
 | 
			
		||||
 | 
			
		||||
const val TEST_PCR = "LP6464-4"
 | 
			
		||||
const val TEST_ANTIGENIC = "LP217198-3"
 | 
			
		||||
const val TEST_ANTIGENIC = "LP217198-3"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// TousAntiCovid resources
 | 
			
		||||
const val TAC_RES_BASE_URL = "https://app.tousanticovid.gouv.fr/json/version-38/"
 | 
			
		||||
@@ -1,8 +1,23 @@
 | 
			
		||||
package org.communiquons.dccaggregator.activities
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.os.PersistableBundle
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity
 | 
			
		||||
import org.communiquons.dccaggregator.DCCAggregator
 | 
			
		||||
import org.communiquons.dccaggregator.apis.initOkHTTP
 | 
			
		||||
 | 
			
		||||
abstract class BaseActivity : AppCompatActivity() {
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        initOkHTTP(this)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState, persistentState)
 | 
			
		||||
 | 
			
		||||
        initOkHTTP(this)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val certsManager get() = (application as DCCAggregator).certManager
 | 
			
		||||
}
 | 
			
		||||
@@ -3,17 +3,20 @@ package org.communiquons.dccaggregator.activities
 | 
			
		||||
import android.app.AlertDialog
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.ContextMenu
 | 
			
		||||
import android.view.Menu
 | 
			
		||||
import android.view.MenuItem
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.widget.AdapterView
 | 
			
		||||
import android.widget.Toast
 | 
			
		||||
import androidx.lifecycle.ViewModelProvider
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanContract
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanOptions
 | 
			
		||||
import org.communiquons.dccaggregator.R
 | 
			
		||||
import org.communiquons.dccaggregator.WALLET_URL
 | 
			
		||||
import org.communiquons.dccaggregator.adapters.CertificatesAdapter
 | 
			
		||||
import org.communiquons.dccaggregator.data.Certificate
 | 
			
		||||
import org.communiquons.dccaggregator.databinding.ActivityCertsManagerBinding
 | 
			
		||||
import org.communiquons.dccaggregator.models.Certificate
 | 
			
		||||
import org.communiquons.dccaggregator.viewmodel.CertsManagerViewModel
 | 
			
		||||
import java.net.URLDecoder
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
 | 
			
		||||
@@ -29,10 +32,17 @@ class CertsManager : BaseActivity() {
 | 
			
		||||
        CertificatesAdapter(this, certsList)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val viewModel by lazy {
 | 
			
		||||
        val viewModel = ViewModelProvider(this).get(CertsManagerViewModel::class.java)
 | 
			
		||||
        viewModel.certsManager = this.certsManager
 | 
			
		||||
        viewModel
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val TAG = CertsManager::class.java.canonicalName
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        binding = ActivityCertsManagerBinding.inflate(layoutInflater)
 | 
			
		||||
        setContentView(binding.root)
 | 
			
		||||
 | 
			
		||||
@@ -54,12 +64,22 @@ class CertsManager : BaseActivity() {
 | 
			
		||||
        refreshList()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
 | 
			
		||||
        menuInflater.inflate(R.menu.cert_manager_top_menu, menu)
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
 | 
			
		||||
        if (item.itemId == android.R.id.home) {
 | 
			
		||||
            finish()
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (item.itemId == R.id.generate_certificate) {
 | 
			
		||||
            generateNewCertificate()
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return super.onOptionsItemSelected(item)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -111,7 +131,7 @@ class CertsManager : BaseActivity() {
 | 
			
		||||
    ) {
 | 
			
		||||
        super.onCreateContextMenu(menu, v, menuInfo)
 | 
			
		||||
        if (v == binding.certsList)
 | 
			
		||||
            menuInflater.inflate(R.menu.cert_menu, menu)
 | 
			
		||||
            menuInflater.inflate(R.menu.certificate_menu, menu)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onContextItemSelected(item: MenuItem): Boolean {
 | 
			
		||||
@@ -138,4 +158,20 @@ class CertsManager : BaseActivity() {
 | 
			
		||||
            show()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun generateNewCertificate() {
 | 
			
		||||
        val dialog = AlertDialog.Builder(this)
 | 
			
		||||
            .setView(R.layout.generating_dialog)
 | 
			
		||||
            .show().apply {
 | 
			
		||||
                setCancelable(false)
 | 
			
		||||
                setCanceledOnTouchOutside(false)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        // TODO: hum hum
 | 
			
		||||
        viewModel.requestCertificate()
 | 
			
		||||
 | 
			
		||||
        // Close dialog
 | 
			
		||||
        dialog.cancel()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@ import com.journeyapps.barcodescanner.BarcodeEncoder
 | 
			
		||||
import org.communiquons.dccaggregator.R
 | 
			
		||||
import org.communiquons.dccaggregator.databinding.QrEntryBinding
 | 
			
		||||
import org.communiquons.dccaggregator.ext.toDimensSize
 | 
			
		||||
import org.communiquons.dccaggregator.models.Certificate
 | 
			
		||||
import org.communiquons.dccaggregator.data.Certificate
 | 
			
		||||
 | 
			
		||||
class CertificatesAdapter(cxt: Context, list: ArrayList<Certificate>) :
 | 
			
		||||
    ArrayAdapter<Certificate>(cxt, 0, list) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <T> getRetrofitService(
 | 
			
		||||
    baseUrl: String,
 | 
			
		||||
    clazz: Class<T>,
 | 
			
		||||
): T {
 | 
			
		||||
    return Retrofit.Builder()
 | 
			
		||||
        .baseUrl(baseUrl.toHttpUrl())
 | 
			
		||||
        .addConverterFactory(GsonConverterFactory.create())
 | 
			
		||||
        .client(defaultOkHTTPClient!!)
 | 
			
		||||
        .build().create(clazz)
 | 
			
		||||
}
 | 
			
		||||
@@ -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<ConfigurationEntry>)
 | 
			
		||||
 | 
			
		||||
class ParsedConfig(val activityPassGenerationServerPublicKey: String)
 | 
			
		||||
 | 
			
		||||
interface TousAntiCovidAPI {
 | 
			
		||||
    @GET("Config/config.json")
 | 
			
		||||
    suspend fun config(): Response<ConfigurationWrapper>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package org.communiquons.dccaggregator.models
 | 
			
		||||
package org.communiquons.dccaggregator.data
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import dgca.verifier.app.decoder.CertificateDecodingResult
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_check.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_check.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
<vector android:height="24dp" android:tint="#FFFFFF"
 | 
			
		||||
    android:viewportHeight="24" android:viewportWidth="24"
 | 
			
		||||
    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <path android:fillColor="@android:color/white" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										29
									
								
								app/src/main/res/layout/generating_dialog.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/src/main/res/layout/generating_dialog.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    android:layout_width="wrap_content"
 | 
			
		||||
    android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/textView"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_marginTop="32dp"
 | 
			
		||||
        android:layout_marginBottom="32dp"
 | 
			
		||||
        android:text="@string/generating_certificate"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent" />
 | 
			
		||||
 | 
			
		||||
    <ProgressBar
 | 
			
		||||
        android:id="@+id/progressBar"
 | 
			
		||||
        style="?android:attr/progressBarStyle"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_marginTop="32dp"
 | 
			
		||||
        android:layout_marginBottom="32dp"
 | 
			
		||||
        app:layout_constraintBottom_toTopOf="@+id/textView"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent" />
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
							
								
								
									
										9
									
								
								app/src/main/res/menu/cert_manager_top_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/menu/cert_manager_top_menu.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <item
 | 
			
		||||
        android:id="@+id/generate_certificate"
 | 
			
		||||
        android:icon="@drawable/ic_check"
 | 
			
		||||
        android:title="@string/generate_certificate"
 | 
			
		||||
        app:showAsAction="always" />
 | 
			
		||||
</menu>
 | 
			
		||||
							
								
								
									
										41
									
								
								app/src/main/res/raw/internal_july_2017.pem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/src/main/res/raw/internal_july_2017.pem
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIHJzCCBI+gAwIBAgIJAN1HrXxMdGLnMA0GCSqGSIb3DQEBDQUAMIGoMQswCQYD
 | 
			
		||||
VQQGEwJGUjEOMAwGA1UECAwFTG9pcmUxFjAUBgNVBAcMDVNhaW50LUV0aWVubmUx
 | 
			
		||||
GjAYBgNVBAoMEUludGVybmFsIFNlcnZpY2VzMREwDwYDVQQLDAhTZWN1cml0eTEZ
 | 
			
		||||
MBcGA1UEAwwQSU5URVJOQUwgUk9PVCBDQTEnMCUGCSqGSIb3DQEJARYYY29udGFj
 | 
			
		||||
dEBjb21tdW5pcXVvbnMub3JnMCAXDTE3MDcxNzA4MjMzMFoYDzIwNjcwNzA1MDgy
 | 
			
		||||
MzMwWjCBqDELMAkGA1UEBhMCRlIxDjAMBgNVBAgMBUxvaXJlMRYwFAYDVQQHDA1T
 | 
			
		||||
YWludC1FdGllbm5lMRowGAYDVQQKDBFJbnRlcm5hbCBTZXJ2aWNlczERMA8GA1UE
 | 
			
		||||
CwwIU2VjdXJpdHkxGTAXBgNVBAMMEElOVEVSTkFMIFJPT1QgQ0ExJzAlBgkqhkiG
 | 
			
		||||
9w0BCQEWGGNvbnRhY3RAY29tbXVuaXF1b25zLm9yZzCCAqIwDQYJKoZIhvcNAQEB
 | 
			
		||||
BQADggKPADCCAooCggKBAM01AqYT14dlRoCHzv34j7gJUjrz3rxgnmo64+dr+EK9
 | 
			
		||||
P13SUlhH5RWD0zl03o+BN7GmfeSmxxhdj05NX5ImBe1+ZM31K6JOjJv4zTP+8Jvr
 | 
			
		||||
kVkgHkA5brP3Kyy7geFKDnH6lRjfG+66Ms+ch6TzdZr6/f5Cd6WBNpF68iJQ9oN1
 | 
			
		||||
sjVEjIYyjL8+HclErGWHdRP28QQZ+gjeq+DoD2l4wijVg+7cdOaU2NzbBYEpXeQD
 | 
			
		||||
TnLvbyUZ1wrcSCqvH1ovGdVicN1pZWYsuRC0isD1JVKs15qtFVfJcw2sFd5PfykW
 | 
			
		||||
PzHy3FeXwGV9UcBMwFoqvD6iW4oE3Jk7lq6+dZFJgJ7hR7HwDYBbU5eSnbVEM6pV
 | 
			
		||||
N7IkDEfkE8JpYd1Y0VI35jFaSVAhm1/yMrEzIfiRNQPtnlQbc069Y4cYV47mfNPB
 | 
			
		||||
Ms6YifY1PJ++0yZPLyZXHRvYj+rbJzTfXTcD77IPtbBe5PnAlR+T4mO4VYa6fQlM
 | 
			
		||||
pRhaNF2cUjWrjR2QaeIf6oBg9Pgtr2Q1JTG4ugBa972kQLYQAV3Hv1Kkm+RzB8qx
 | 
			
		||||
P2ZFd7ZBKXqp1f5jVdfCOa46L4jTbW3x9pgRAwX4Rz8LrepKgEzGtJNazZk0hDoO
 | 
			
		||||
R+BSKTBQT1F+Tg44stDK8pUfdlVS9iVcai8r9MXbLkp8f2K9Hk6/vpuv+fcjB6oP
 | 
			
		||||
qWNrdMBdTJsXgfoHM7RnEE4IxKwg+Gx/laH/yQHW8Y8MlrxqmderyhupjhYHBlnd
 | 
			
		||||
+H0hQUSWk8WzeVhvVS/rcml/MEBSIo1PS0dLmlDgBmk1ZTTR14vc7eSbV/swyhC7
 | 
			
		||||
LTVE0zIOLxRY+i8W2SdpMYfP2O7CXf85V1mAtVViygECAwEAAaNQME4wHQYDVR0O
 | 
			
		||||
BBYEFAGTweo8SYVcz2esZRkp8UnDy9bxMB8GA1UdIwQYMBaAFAGTweo8SYVcz2es
 | 
			
		||||
ZRkp8UnDy9bxMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQENBQADggKBAH0A76f/
 | 
			
		||||
iY71J9RD8qO8yNiSlp75/DuPGcY4vfJ3LaJuhISew6uc5o7s/8nMIiF89Ol+vfVP
 | 
			
		||||
DFUr6XeSe21hb32mAWghaZFcVhxJxJNSD3ehF6CaLoyxgY81advaCl/LQWdfQh4U
 | 
			
		||||
BoiYhNJlUkH/pD3oUN4pnqaCu2la0aCuyLEHFIhcAfdmpPYdLEL22o7ckXvD+TIf
 | 
			
		||||
0ozkF1bXysRC7Ngz5QEfxQsykMwcwu+T8F1c4mGGFG17L5Q+2cvsUHFYegCkoQO3
 | 
			
		||||
jeyKG4vfRmFiqvMA8zWLXO1zns2dCSEHqGGkWdqbf1Gb07vImx7oz+Gmp9jU1l+j
 | 
			
		||||
l4520H9bBwAmGUk+op+Kr4EHunn8fzpkP6KhjFf3Eu0eszLSWJeJFJS8Qj7vT7Vo
 | 
			
		||||
steSVbrjbttdrkKJKfj4IU+4kiAADcwVAK2Sng77OtylE4QezvRjeQfmYmSQXgYi
 | 
			
		||||
6WWfwezTU6omW993XMv4RcKrOWyR18RcbZrt4jgOkCRVN9TLX/ZJh6/61iadywkD
 | 
			
		||||
NW7vfoYGzzh2IBDDZGhLpfHFv8r9qxEMhvnJUzdKH9d4VZuZlwnCDPHbjkUzJqdo
 | 
			
		||||
VG5k5e2O3xE900U8DFO4jpImhHJO4ADKXaHw0uo2jJHllTB54iLdMXRh12kn3emS
 | 
			
		||||
xYlOxfYeGWVLxM0zA9kZ9b9AzH65m8OIhl/EFGX5hLIV7yK9VFr/elxCuMr+/6jT
 | 
			
		||||
cSQA/1eYnCctjkTZh65RD1e449mobjG5cH+SwS+LMHAUQXng8l1m6DvwPzVGUXBO
 | 
			
		||||
zhpfX+8K/aD2lSRT8aoyiS5yy6MXnJKP7K8KJqXbNYzbtZQvo8IN+JuD93ilXoYa
 | 
			
		||||
YfHRSwb9eV4oxZk=
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
@@ -22,4 +22,6 @@
 | 
			
		||||
    <string name="remove_cert">Remove certificate</string>
 | 
			
		||||
    <string name="msg_confirm_remove_cert">Do you really want to remove this certificate from the list?</string>
 | 
			
		||||
    <string name="no">No</string>
 | 
			
		||||
    <string name="generate_certificate">Generate certificate</string>
 | 
			
		||||
    <string name="generating_certificate">Waiting for your certificate, please wait…</string>
 | 
			
		||||
</resources>
 | 
			
		||||
		Reference in New Issue
	
	Block a user