Parse input certificates

This commit is contained in:
Pierre HUBERT 2022-02-16 10:52:58 +01:00
parent d2847107b4
commit 2b6fe21792
8 changed files with 97 additions and 3 deletions

View File

@ -23,6 +23,8 @@ android {
} }
} }
compileOptions { compileOptions {
coreLibraryDesugaringEnabled = true
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
@ -33,6 +35,15 @@ android {
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
} }
packagingOptions {
pickFirst 'META-INF/ASL-2.0.txt'
pickFirst 'draftv4/schema'
pickFirst 'draftv3/schema'
pickFirst 'META-INF/LGPL-3.0.txt'
}
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
} }
dependencies { dependencies {
@ -42,8 +53,11 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.preference:preference:1.2.0' implementation 'androidx.preference:preference:1.2.0'
implementation 'com.journeyapps:zxing-android-embedded:4.3.0' 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'
testImplementation 'junit:junit:4.+' testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
} }

View File

@ -29,8 +29,22 @@
<!-- Manage certificates --> <!-- Manage certificates -->
<activity <activity
android:name=".activities.CertsManager" android:name=".activities.CertsManager"
android:exported="false" android:exported="true"
android:label="@string/activity_certsmanagers" /> android:label="@string/activity_certsmanagers">
<intent-filter android:label="@string/action_import_certificate">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="bonjour.tousanticovid.gouv.fr"
android:pathPrefix="/app/walletdcc"
android:scheme="https" />
</intent-filter>
</activity>
<!-- Fix Qr scanner orientation --> <!-- Fix Qr scanner orientation -->
<activity <activity

View File

@ -0,0 +1,4 @@
package org.communiquons.dccaggregator
// Official URL provided to add certificate to wallet
const val WALLET_URL = "https://bonjour.tousanticovid.gouv.fr/app/walletdcc#"

View File

@ -3,11 +3,16 @@ package org.communiquons.dccaggregator.activities
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions import com.journeyapps.barcodescanner.ScanOptions
import org.communiquons.dccaggregator.R import org.communiquons.dccaggregator.R
import org.communiquons.dccaggregator.WALLET_URL
import org.communiquons.dccaggregator.databinding.ActivityCertsManagerBinding import org.communiquons.dccaggregator.databinding.ActivityCertsManagerBinding
import org.communiquons.dccaggregator.models.Certificate
import java.net.URLDecoder
import java.nio.charset.StandardCharsets
class CertsManager : AppCompatActivity() { class CertsManager : AppCompatActivity() {
@ -25,6 +30,12 @@ class CertsManager : AppCompatActivity() {
binding.scanCertButton.setOnClickListener { binding.scanCertButton.setOnClickListener {
addNewCertificate() addNewCertificate()
} }
intent?.dataString.toString().apply {
if (this.startsWith(WALLET_URL))
processGivenCertificate(this)
}
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -40,7 +51,7 @@ class CertsManager : AppCompatActivity() {
if (it.contents == null) if (it.contents == null)
return@registerForActivityResult return@registerForActivityResult
Log.v(TAG, it.contents) processGivenCertificate(it.contents)
} }
private fun addNewCertificate() { private fun addNewCertificate() {
@ -50,4 +61,24 @@ class CertsManager : AppCompatActivity() {
setPrompt(resources.getString(R.string.scan_qr_prompt)) setPrompt(resources.getString(R.string.scan_qr_prompt))
}) })
} }
private fun processGivenCertificate(input: String) {
// Decode input if required
val decoded = if (input.startsWith(WALLET_URL)) {
URLDecoder.decode(input.replace(WALLET_URL, ""), StandardCharsets.UTF_8.displayName())
} else {
input
}
try {
val cert = Certificate(decoded)
Log.v(TAG, cert.fullName)
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this, R.string.invalid_certificate, Toast.LENGTH_SHORT).show()
return
}
}
} }

View File

@ -0,0 +1,27 @@
package org.communiquons.dccaggregator.models
import dgca.verifier.app.decoder.CertificateDecodingResult
import dgca.verifier.app.decoder.DefaultCertificateDecoder
import dgca.verifier.app.decoder.base45.Base45Decoder
import dgca.verifier.app.decoder.model.GreenCertificate
@OptIn(ExperimentalUnsignedTypes::class)
class Certificate(val encoded: String) {
// Decoded green certificate
val decoded: GreenCertificate;
init {
val res = DefaultCertificateDecoder(Base45Decoder()).decodeCertificate(encoded)
if (res is CertificateDecodingResult.Error)
throw Exception("Failed to read certificate!", res.error.error)
decoded = (res as CertificateDecodingResult.Success).greenCertificate
}
/**
* Get person full name
*/
val fullName get() = "${decoded.person.standardisedGivenName} ${decoded.person.standardisedFamilyName}"
}

View File

@ -3,4 +3,6 @@
<string name="activity_certsmanagers">Input certificates</string> <string name="activity_certsmanagers">Input certificates</string>
<string name="add_certificate">Add a new certificate</string> <string name="add_certificate">Add a new certificate</string>
<string name="scan_qr_prompt">Please present the QrCode of the certificate you want to add</string> <string name="scan_qr_prompt">Please present the QrCode of the certificate you want to add</string>
<string name="action_import_certificate">Import certificate</string>
<string name="invalid_certificate">The given certificate could not be decoded!</string>
</resources> </resources>

View File

@ -3,6 +3,7 @@ buildscript {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven { url 'https://jitpack.io' }
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:7.0.4" classpath "com.android.tools.build:gradle:7.0.4"

View File

@ -3,6 +3,7 @@ dependencyResolutionManagement {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven { url 'https://jitpack.io' }
jcenter() // Warning: this repository is going to shut down soon jcenter() // Warning: this repository is going to shut down soon
} }
} }