Skip to content

Commit 0fb6b05

Browse files
committed
Validation: Treat all errors the same
1 parent 662e839 commit 0fb6b05

7 files changed

Lines changed: 47 additions & 57 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Release 5.9.0 (unreleased):
44
- Remove code elements deprecated in 5.8.0
55
- Validation:
66
- Improve validation of JWT VC
7+
- Remove subclass `InvalidStructure` from `Verifier.VerifyCredentialResult`, is now mapped to `ValidationError`
78

89
Release 5.8.0:
910
- Refactor `AuthorizationServiceStrategy`

vck/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/ValidatorMdoc.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ import at.asitplus.iso.ValueDigestList
99
import at.asitplus.iso.sha256
1010
import at.asitplus.iso.wrapInCborTag
1111
import at.asitplus.signum.indispensable.cosef.CoseKey
12-
import at.asitplus.signum.indispensable.cosef.io.Base16Strict
1312
import at.asitplus.signum.indispensable.cosef.io.ByteStringWrapper
1413
import at.asitplus.signum.indispensable.cosef.io.coseCompliantSerializer
1514
import at.asitplus.signum.indispensable.cosef.toCoseKey
1615
import at.asitplus.signum.indispensable.pki.X509Certificate
1716
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult
18-
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult.InvalidStructure
1917
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult.SuccessIso
2018
import at.asitplus.wallet.lib.agent.Verifier.VerifyPresentationResult
2119
import at.asitplus.wallet.lib.agent.validation.mdoc.MdocInputValidator
@@ -26,7 +24,6 @@ import io.github.aakira.napier.Napier
2624
import io.matthewnelson.encoding.base64.Base64
2725
import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
2826
import kotlinx.serialization.builtins.ByteArraySerializer
29-
import kotlinx.serialization.encodeToByteArray
3027
import kotlin.coroutines.cancellation.CancellationException
3128

3229
class ValidatorMdoc(
@@ -162,9 +159,8 @@ class ValidatorMdoc(
162159
Napier.d("Verifying ISO Cred $it")
163160
val mdocInputValidator = mdocInputValidator(it, issuerKey)
164161
if (!mdocInputValidator.isSuccess) {
165-
return InvalidStructure(
166-
input = coseCompliantSerializer.encodeToByteArray(it).encodeToString(Base16Strict),
167-
reason = mdocInputValidator.integrityValidationSummary.toString()
162+
return VerifyCredentialResult.ValidationError(
163+
cause = mdocInputValidator.error ?: IllegalArgumentException("No details available")
168164
)
169165
}
170166
return SuccessIso(it)

vck/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/ValidatorVcJws.kt

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package at.asitplus.wallet.lib.agent
33
import at.asitplus.signum.indispensable.CryptoPublicKey
44
import at.asitplus.signum.indispensable.josef.JwsSigned
55
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult
6-
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult.*
6+
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult.SuccessJwt
7+
import at.asitplus.wallet.lib.agent.Verifier.VerifyCredentialResult.ValidationError
78
import at.asitplus.wallet.lib.agent.Verifier.VerifyPresentationResult
8-
import at.asitplus.wallet.lib.agent.validation.vcJws.VcJwsInputValidationResult
9+
import at.asitplus.wallet.lib.agent.validation.vcJws.VcJwsInputValidationResult.ContentValidationSummary
10+
import at.asitplus.wallet.lib.agent.validation.vcJws.VcJwsInputValidationResult.ParsingError
911
import at.asitplus.wallet.lib.agent.validation.vcJws.VcJwsInputValidator
1012
import at.asitplus.wallet.lib.data.VcDataModelConstants.VERIFIABLE_PRESENTATION
1113
import at.asitplus.wallet.lib.data.VcJwsVerificationResultWrapper
@@ -132,7 +134,7 @@ class ValidatorVcJws(
132134
suspend fun verifyVcJws(
133135
input: JwsSigned<VerifiableCredentialJws>,
134136
publicKey: CryptoPublicKey?,
135-
vpJws: JwsSigned<VerifiablePresentationJws>? = null
137+
vpJws: JwsSigned<VerifiablePresentationJws>? = null,
136138
) = verifyVcJws(input.serialize(), publicKey, vpJws)
137139

138140
/**
@@ -145,34 +147,17 @@ class ValidatorVcJws(
145147
suspend fun verifyVcJws(
146148
input: String,
147149
publicKey: CryptoPublicKey?,
148-
vpJws: JwsSigned<VerifiablePresentationJws>? = null
149-
): VerifyCredentialResult {
150-
Napier.d("Validating VC-JWS $input")
151-
val validationSummary = vcJwsInputValidator(input, publicKey, vpJws)
152-
return when {
153-
validationSummary !is VcJwsInputValidationResult.ContentValidationSummary -> InvalidStructure(
154-
input = input,
155-
reason = validationSummary.toString()
156-
)
157-
158-
!validationSummary.isIntegrityGood -> InvalidStructure(
159-
input = input,
160-
reason = "!isIntegrityGood"
161-
)
162-
163-
!validationSummary.contentSemanticsValidationSummary.isSuccess -> InvalidStructure(
164-
input = input,
165-
reason = validationSummary.contentSemanticsValidationSummary.toString()
166-
)
167-
168-
validationSummary.subjectMatchingResult?.isSuccess == false ->
169-
ValidationError("subject not matching key")
170-
171-
validationSummary.isSuccess ->
172-
SuccessJwt(validationSummary.payload)
173-
174-
else -> ValidationError(input) // this branch shouldn't be executed anyway
150+
vpJws: JwsSigned<VerifiablePresentationJws>? = null,
151+
): VerifyCredentialResult =
152+
when (val result = vcJwsInputValidator(input, publicKey, vpJws)) {
153+
is ParsingError -> ValidationError(result.throwable)
154+
is ContentValidationSummary ->
155+
if (result.isSuccess)
156+
SuccessJwt(result.payload)
157+
else
158+
ValidationError(result.toString())
159+
}.also {
160+
Napier.d("Validating VC-JWS $input got $it")
175161
}
176-
}
177162

178163
}

vck/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/Verifier.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ interface Verifier {
9696
val issuerSigned: IssuerSigned,
9797
) : VerifyCredentialResult()
9898

99+
@Deprecated("Has been replaced with ValidationError")
99100
data class InvalidStructure(
100101
val input: String,
101102
val reason: String,

vck/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/validation/mdoc/MdocInputValidationSummary.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,24 @@ data class MdocInputValidationSummary(
99
integrityValidationSummary.isSuccess,
1010
).all { it }
1111

12+
val error = integrityValidationSummary.error
13+
1214
sealed interface IntegrityValidationSummary {
1315
val isSuccess: Boolean
16+
val error: Throwable?
1417

15-
data object IntegrityNotValidated : IntegrityValidationSummary {
18+
data object IntegrityNotValidated
19+
: IntegrityValidationSummary {
1620
override val isSuccess: Boolean
1721
get() = false
22+
override val error: Throwable?
23+
get() = IllegalArgumentException("No issuer key")
1824
}
1925

2026
data class IntegrityValidationResult(
2127
val issuerKey: CoseKey,
2228
override val isSuccess: Boolean,
29+
override val error: Throwable?,
2330
) : IntegrityValidationSummary
2431
}
2532
}

vck/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/validation/mdoc/MdocInputValidator.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package at.asitplus.wallet.lib.agent.validation.mdoc
33
import at.asitplus.iso.IssuerSigned
44
import at.asitplus.iso.MobileSecurityObject
55
import at.asitplus.signum.indispensable.cosef.CoseKey
6+
import at.asitplus.wallet.lib.agent.validation.mdoc.MdocInputValidationSummary.IntegrityValidationSummary
67
import at.asitplus.wallet.lib.cbor.VerifyCoseSignatureWithKey
78
import at.asitplus.wallet.lib.cbor.VerifyCoseSignatureWithKeyFun
89
import io.github.aakira.napier.Napier
@@ -13,20 +14,19 @@ class MdocInputValidator(
1314
) {
1415
suspend operator fun invoke(it: IssuerSigned, issuerKey: CoseKey?) = MdocInputValidationSummary(
1516
integrityValidationSummary = if (issuerKey == null) {
16-
Napier.w("ISO: No issuer key")
17-
MdocInputValidationSummary.IntegrityValidationSummary.IntegrityNotValidated
17+
Napier.w("MdocInputValidator: No issuer key")
18+
IntegrityValidationSummary.IntegrityNotValidated
1819
} else {
19-
MdocInputValidationSummary.IntegrityValidationSummary.IntegrityValidationResult(
20+
val verifyCoseSignatureWithKey = verifyCoseSignatureWithKey(it.issuerAuth, issuerKey, byteArrayOf(), null)
21+
.onFailure { Napier.w("MdocInputValidator: Could not verify credential", it) }
22+
IntegrityValidationSummary.IntegrityValidationResult(
2023
issuerKey = issuerKey,
21-
isSuccess = verifyCoseSignatureWithKey(it.issuerAuth, issuerKey, byteArrayOf(), null).onFailure { ex ->
22-
Napier.w("ISO: Could not verify credential", ex)
23-
}.isSuccess
24+
isSuccess = verifyCoseSignatureWithKey.isSuccess,
25+
error = verifyCoseSignatureWithKey.exceptionOrNull(),
2426
)
2527
},
2628
).also {
27-
if (it.isSuccess) {
28-
Napier.d("Verifying ISO Cred $it")
29-
}
29+
Napier.d("MdocInputValidator: Result: $it")
3030
}
3131
}
3232

vck/src/commonTest/kotlin/at/asitplus/wallet/lib/agent/ValidatorVcTest.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class ValidatorVcTest : FreeSpec() {
137137
validator.verifyVcJws(
138138
credential.signedVcJws.serialize().replaceFirstChar { "f" },
139139
verifierKeyMaterial.publicKey
140-
).shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
140+
).shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
141141
}
142142

143143
"Manually created and valid credential is valid" {
@@ -167,7 +167,7 @@ class ValidatorVcTest : FreeSpec() {
167167
.let { wrapVcInJwsWrongKey(it) }
168168
.let {
169169
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
170-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
170+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
171171
}
172172
}
173173
}
@@ -183,7 +183,7 @@ class ValidatorVcTest : FreeSpec() {
183183
.let { signJws(it) }
184184
.let {
185185
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
186-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
186+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
187187
}
188188
}
189189
}
@@ -198,7 +198,7 @@ class ValidatorVcTest : FreeSpec() {
198198
.let { wrapVcInJws(it, issuer = "vc.issuer") }
199199
.let { signJws(it) }.let {
200200
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
201-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
201+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
202202
}
203203
}
204204
}
@@ -214,7 +214,7 @@ class ValidatorVcTest : FreeSpec() {
214214
.let { signJws(it) }
215215
.let {
216216
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
217-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
217+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
218218
}
219219
}
220220
}
@@ -239,7 +239,7 @@ class ValidatorVcTest : FreeSpec() {
239239
.let { signJws(it) }
240240
.let {
241241
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
242-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
242+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
243243
}
244244
}
245245
}
@@ -271,7 +271,7 @@ class ValidatorVcTest : FreeSpec() {
271271
.let { signJws(it) }
272272
.let {
273273
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
274-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
274+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
275275
}
276276
}
277277
}
@@ -287,7 +287,7 @@ class ValidatorVcTest : FreeSpec() {
287287
.let { signJws(it) }
288288
.let {
289289
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
290-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
290+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
291291
}
292292
}
293293
}
@@ -303,7 +303,7 @@ class ValidatorVcTest : FreeSpec() {
303303
.let { signJws(it) }
304304
.let {
305305
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
306-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
306+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
307307
}
308308
}
309309
}
@@ -337,7 +337,7 @@ class ValidatorVcTest : FreeSpec() {
337337
.let { signJws(it) }
338338
.let {
339339
validator.verifyVcJws(it, verifierKeyMaterial.publicKey)
340-
.shouldBeInstanceOf<VerifyCredentialResult.InvalidStructure>()
340+
.shouldBeInstanceOf<VerifyCredentialResult.ValidationError>()
341341
}
342342
}
343343
}

0 commit comments

Comments
 (0)