Skip to content

Commit 223ea28

Browse files
Updated to make it possible to have several keys with the same kid (eu-digital-green-certificates#38)
* Updated to make it possible to have several keys with the same kid * Updated verification logic
1 parent 6122b18 commit 223ea28

File tree

5 files changed

+33
-28
lines changed

5 files changed

+33
-28
lines changed

app/src/main/java/dgca/verifier/app/android/data/VerifierRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ interface VerifierRepository {
2828

2929
suspend fun fetchCertificates(): Boolean?
3030

31-
suspend fun getCertificate(kid: String): Certificate?
31+
suspend fun getCertificatesBy(kid: String): List<Certificate>
3232
}

app/src/main/java/dgca/verifier/app/android/data/VerifierRepositoryImpl.kt

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ import java.security.cert.Certificate
3636
import javax.inject.Inject
3737

3838
class VerifierRepositoryImpl @Inject constructor(
39-
private val apiService: ApiService,
40-
private val preferences: Preferences,
41-
private val db: AppDatabase,
42-
private val keyStoreCryptor: KeyStoreCryptor
39+
private val apiService: ApiService,
40+
private val preferences: Preferences,
41+
private val db: AppDatabase,
42+
private val keyStoreCryptor: KeyStoreCryptor
4343
) : BaseRepository(), VerifierRepository {
4444

4545
private val validCertList = mutableListOf<String>()
@@ -58,9 +58,8 @@ class VerifierRepositoryImpl @Inject constructor(
5858
}
5959
}
6060

61-
override suspend fun getCertificate(kid: String): Certificate? {
62-
val key = db.keyDao().getById(kid)
63-
return if (key != null) keyStoreCryptor.decrypt(key.key)?.base64ToX509Certificate() else null
61+
override suspend fun getCertificatesBy(kid: String): List<Certificate> {
62+
return db.keyDao().getByKid(kid).map { keyStoreCryptor.decrypt(it.key)?.base64ToX509Certificate()!! }
6463
}
6564

6665
private suspend fun fetchCertificate(resumeToken: Long) {
@@ -79,7 +78,7 @@ class VerifierRepositoryImpl @Inject constructor(
7978

8079
if (validCertList.contains(responseKid) && isKidValid(responseKid, responseStr)) {
8180
Timber.d("Cert KID verified")
82-
val key = Key(responseKid!!, keyStoreCryptor.encrypt(responseStr)!!)
81+
val key = Key(kid = responseKid!!, key = keyStoreCryptor.encrypt(responseStr)!!)
8382
db.keyDao().insert(key)
8483
}
8584

@@ -95,9 +94,9 @@ class VerifierRepositoryImpl @Inject constructor(
9594

9695
val cert = responseStr.base64ToX509Certificate() ?: return false
9796
val certKid = MessageDigest.getInstance("SHA-256")
98-
.digest(cert.encoded)
99-
.copyOf(8)
100-
.toBase64()
97+
.digest(cert.encoded)
98+
.copyOf(8)
99+
.toBase64()
101100

102101
return responseKid == certKid
103102
}

app/src/main/java/dgca/verifier/app/android/data/local/Key.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import androidx.room.PrimaryKey
2727

2828
@Entity(tableName = "keys")
2929
data class Key(
30-
31-
@PrimaryKey val kid: String,
32-
val key: String
30+
@PrimaryKey(autoGenerate = true)
31+
val id: Int = 0,
32+
val kid: String,
33+
val key: String
3334
)

app/src/main/java/dgca/verifier/app/android/data/local/KeyDao.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ interface KeyDao {
3636
@Query("SELECT * FROM keys WHERE kid IN (:keyIds)")
3737
fun getAllByIds(keyIds: Array<String>): List<Key>
3838

39-
@Query("SELECT * FROM keys WHERE kid LIKE :kid LIMIT 1")
40-
fun getById(kid: String): Key?
39+
@Query("SELECT * FROM keys WHERE kid LIKE :kid")
40+
fun getByKid(kid: String): List<Key>
4141

4242
@Query("DELETE FROM keys WHERE kid = :kid")
4343
fun deleteById(kid: String)

app/src/main/java/dgca/verifier/app/android/verification/VerificationViewModel.kt

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ import javax.inject.Inject
4949

5050
@HiltViewModel
5151
class VerificationViewModel @Inject constructor(
52-
private val prefixValidationService: PrefixValidationService,
53-
private val base45Service: Base45Service,
54-
private val compressorService: CompressorService,
55-
private val cryptoService: CryptoService,
56-
private val coseService: CoseService,
57-
private val schemaValidator: SchemaValidator,
58-
private val cborService: CborService,
59-
private val verifierRepository: VerifierRepository
52+
private val prefixValidationService: PrefixValidationService,
53+
private val base45Service: Base45Service,
54+
private val compressorService: CompressorService,
55+
private val cryptoService: CryptoService,
56+
private val coseService: CoseService,
57+
private val schemaValidator: SchemaValidator,
58+
private val cborService: CborService,
59+
private val verifierRepository: VerifierRepository
6060
) : ViewModel() {
6161

6262
private val _verificationResult = MutableLiveData<VerificationResult>()
@@ -99,12 +99,17 @@ class VerificationViewModel @Inject constructor(
9999
greenCertificate = cborService.decode(coseData.cbor, verificationResult)
100100
validateCertData(greenCertificate, verificationResult)
101101

102-
val certificate = verifierRepository.getCertificate(kid.toBase64())
103-
if (certificate == null) {
102+
val certificates = verifierRepository.getCertificatesBy(kid.toBase64())
103+
if (certificates.isEmpty()) {
104104
Timber.d("Verification failed: failed to load certificate")
105105
return@withContext
106106
}
107-
cryptoService.validate(cose, certificate, verificationResult)
107+
certificates.forEach { innerCertificate ->
108+
cryptoService.validate(cose, innerCertificate, verificationResult)
109+
if (verificationResult.coseVerified) {
110+
return@forEach
111+
}
112+
}
108113
}
109114

110115
_inProgress.value = false

0 commit comments

Comments
 (0)