From 7b4eaa3a023f0a3a25ae9fa8b60010bb1d87e8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Thu, 29 Aug 2024 13:31:56 +0200 Subject: [PATCH 01/13] update to newest vck API --- .../at/asitplus/wallet/mdl/Initializer.kt | 23 ++++++++++++++++--- .../wallet/mdl/MobileDrivingLicence.kt | 1 + .../wallet/mdl/CborSerializationTest.kt | 19 ++++++++------- .../at/asitplus/wallet/mdl/IsoMdocTest.kt | 16 ++++++------- settings.gradle.kts | 8 +++++++ 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt index f1185f9..8c63f21 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt @@ -1,12 +1,16 @@ package at.asitplus.wallet.mdl +import at.asitplus.signum.indispensable.io.ByteArrayBase64UrlSerializer import at.asitplus.wallet.lib.ItemValueDecoder import at.asitplus.wallet.lib.ItemValueEncoder import at.asitplus.wallet.lib.JsonValueEncoder import at.asitplus.wallet.lib.LibraryInitializer import at.asitplus.wallet.lib.SerializerLookup import at.asitplus.wallet.lib.data.jsonSerializer +import kotlinx.datetime.LocalDate import kotlinx.serialization.builtins.ArraySerializer +import kotlinx.serialization.builtins.ByteArraySerializer +import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.CompositeEncoder import kotlinx.serialization.json.encodeToJsonElement @@ -29,8 +33,21 @@ object Initializer { credentialScheme = MobileDrivingLicenceScheme, serializerLookup = serializerLookup(), itemValueEncoder = itemValueEncoder(), - itemValueDecoder = itemValueDecoder(), - jsonValueEncoder = jsonValueEncoder() + jsonValueEncoder = jsonValueEncoder(), + itemValueDecoderMap = mapOf( + MobileDrivingLicenceDataElements.BIRTH_DATE to LocalDate.serializer(), + MobileDrivingLicenceDataElements.ISSUE_DATE to LocalDate.serializer(), + MobileDrivingLicenceDataElements.EXPIRY_DATE to LocalDate.serializer(), + MobileDrivingLicenceDataElements.PORTRAIT to ByteArraySerializer(), + MobileDrivingLicenceDataElements.DRIVING_PRIVILEGES to ArraySerializer(DrivingPrivilege.serializer()), + MobileDrivingLicenceDataElements.SEX to IsoSexEnumSerializer, + MobileDrivingLicenceDataElements.HEIGHT to UInt.serializer(), + MobileDrivingLicenceDataElements.WEIGHT to UInt.serializer(), + MobileDrivingLicenceDataElements.PORTRAIT_CAPTURE_DATE to LocalDate.serializer(), + MobileDrivingLicenceDataElements.AGE_IN_YEARS to UInt.serializer(), + MobileDrivingLicenceDataElements.AGE_BIRTH_YEAR to UInt.serializer(), + MobileDrivingLicenceDataElements.SIGNATURE_USUAL_MARK to ByteArraySerializer(), + ) ) } @@ -63,7 +80,7 @@ object Initializer { ) } - private fun itemValueDecoder(): ItemValueDecoder = { descriptor, index, compositeDecoder -> + private fun drivingPrivilegeDecoder(): ItemValueDecoder = { descriptor, index, compositeDecoder -> compositeDecoder.decodeSerializableElement( descriptor, index, diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt index 664ccd6..e14517a 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt @@ -41,6 +41,7 @@ import kotlinx.datetime.LocalDate import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.cbor.ByteString +import kotlinx.serialization.cbor.ValueTags import kotlinx.serialization.decodeFromByteArray import kotlinx.serialization.encodeToByteArray diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt index 5a6ea79..4cb428a 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt @@ -163,7 +163,7 @@ class CborSerializationTest : FreeSpec({ } // From ISO/IEC 18013-5:2021(E), D4.1.2, page 116 - "!mdoc response" { + "mdoc response" { /** * a3 # map(3) * 67 # text(7) @@ -383,7 +383,6 @@ class CborSerializationTest : FreeSpec({ document.deviceSigned.deviceAuth.deviceMac.shouldNotBeNull() - // TODO "elementValue" in IssuerSignedItem needs a tag 1004u (0xD903EC) iff the value is a date deviceResponse.serialize().encodeToString(Base16(strict = true)) shouldBe input } @@ -424,12 +423,12 @@ class CborSerializationTest : FreeSpec({ 6c656d656e744964656e7469666965726a69737375655f646174656c656c656d656e7456616c7565d903ec6a323031392d31302d3230 """.trimIndent().replace("\n", "").uppercase() - val deserialized = IssuerSignedItem.deserialize(input.decodeToByteArray(Base16(strict = true))) - .getOrThrow().shouldNotBeNull() - val serialized = deserialized.serialize() + // val deserialized = IssuerSignedItem.deserialize(input.decodeToByteArray(Base16(strict = true))) + // .getOrThrow().shouldNotBeNull() + // val serialized = deserialized.serialize() // TODO "elementValue" in IssuerSignedItem needs a tag 1004u (0xD903EC) iff the value is a date - serialized.encodeToString(Base16(strict = true)).uppercase() shouldBe input + // serialized.encodeToString(Base16(strict = true)).uppercase() shouldBe input } "Driving Privilege in IssuerSignedItem from ISO example" { @@ -488,11 +487,11 @@ class CborSerializationTest : FreeSpec({ 03EC6A323031372D30322D32336B6578706972795F64617465D903EC6A323032342D31302D3230 """.trimIndent().replace("\n", "") - val deserialized = IssuerSignedItem.deserialize(input.decodeToByteArray(Base16(strict = true))) - .getOrThrow().shouldNotBeNull() - val serialized = deserialized.serialize() + // val deserialized = IssuerSignedItem.deserialize(input.decodeToByteArray(Base16(strict = true))) + // .getOrThrow().shouldNotBeNull() + // val serialized = deserialized.serialize() - serialized.encodeToString(Base16(strict = true)).uppercase() shouldBe input + // serialized.encodeToString(Base16(strict = true)).uppercase() shouldBe input } // From ISO/IEC 18013-5:2021(E), page 130 diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt index de72d09..9d4556a 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt @@ -124,10 +124,10 @@ class Wallet { Document( docType = MobileDrivingLicenceScheme.isoDocType, issuerSigned = IssuerSigned( - namespaces = mapOf( - MobileDrivingLicenceScheme.isoNamespace to IssuerSignedList(storedMdlItems!!.entries.filter { + namespacedItems = mapOf( + MobileDrivingLicenceScheme.isoNamespace to storedMdlItems!!.entries.filter { it.value.elementIdentifier in requestedKeys - }) + }.map { it.value } ), issuerAuth = storedIssuerAuth!! ), @@ -176,7 +176,7 @@ class Issuer { digestAlgorithm = "SHA-256", valueDigests = mapOf( MobileDrivingLicenceScheme.isoNamespace to ValueDigestList(entries = issuerSigned.map { - ValueDigest.fromIssuerSigned(it) + ValueDigest.fromIssuerSigned(MobileDrivingLicenceScheme.isoNamespace, it) }) ), deviceKeyInfo = walletKeyInfo, @@ -194,10 +194,10 @@ class Issuer { Document( docType = MobileDrivingLicenceScheme.isoDocType, issuerSigned = IssuerSigned( - namespaces = mapOf( - MobileDrivingLicenceScheme.isoNamespace to IssuerSignedList.withItems( - issuerSigned - ) + namespacedItems = mapOf( + MobileDrivingLicenceScheme.isoNamespace to + issuerSigned + ), issuerAuth = coseService.createSignedCose( payload = mso.serializeForIssuerAuth(), diff --git a/settings.gradle.kts b/settings.gradle.kts index ede993a..a32ac70 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,5 +9,13 @@ pluginManagement { } } +includeBuild("..") { + dependencySubstitution { + substitute(module("at.asitplus.wallet:vck")).using(project(":vck")) + substitute(module("at.asitplus.wallet:vck-openid")).using(project(":vck-openid")) + substitute(module("at.asitplus.wallet:vck-aries")).using(project(":vck-aries")) + } +} + rootProject.name = "mobile-driving-licence" include(":mobiledrivinglicence") From 14881e5af6fe7948d7b2a8ca781fbac8d59b2a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Thu, 5 Sep 2024 20:48:27 +0200 Subject: [PATCH 02/13] build fixes + cleanups --- build.gradle.kts | 2 +- gradle.properties | 2 +- .../at/asitplus/wallet/mdl/Initializer.kt | 18 ++++-------------- settings.gradle.kts | 1 + 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0d711a9..2b6230b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("at.asitplus.gradle.conventions") version "2.0.0+20240725" + id("at.asitplus.gradle.conventions") version "2.0.0+20240905" } val artifactVersion: String by extra diff --git a/gradle.properties b/gradle.properties index 9196f1f..115ff1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,5 +12,5 @@ kotlin.mpp.enableCInteropCommonization=true kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -artifactVersion = 1.0.3 +artifactVersion = 1.1.0-SNAPSHOT jdk.version=17 diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt index 8c63f21..7063f89 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt @@ -1,12 +1,10 @@ package at.asitplus.wallet.mdl -import at.asitplus.signum.indispensable.io.ByteArrayBase64UrlSerializer -import at.asitplus.wallet.lib.ItemValueDecoder import at.asitplus.wallet.lib.ItemValueEncoder import at.asitplus.wallet.lib.JsonValueEncoder import at.asitplus.wallet.lib.LibraryInitializer import at.asitplus.wallet.lib.SerializerLookup -import at.asitplus.wallet.lib.data.jsonSerializer +import at.asitplus.wallet.lib.data.vckJsonSerializer import kotlinx.datetime.LocalDate import kotlinx.serialization.builtins.ArraySerializer import kotlinx.serialization.builtins.ByteArraySerializer @@ -25,8 +23,8 @@ object Initializer { } /** - * This has to be called first, before anything first, to load the - * relevant classes of this library into the base implementations of VC-K + * This has to be called first, before anything, to load the + * relevant classes' serializer's of this library into the base implementations of VC-K */ fun initWithVCK() { LibraryInitializer.registerExtensionLibrary( @@ -80,16 +78,8 @@ object Initializer { ) } - private fun drivingPrivilegeDecoder(): ItemValueDecoder = { descriptor, index, compositeDecoder -> - compositeDecoder.decodeSerializableElement( - descriptor, - index, - ArraySerializer(DrivingPrivilege.serializer()) - ) - } - private fun jsonValueEncoder(): JsonValueEncoder = { - if (it is DrivingPrivilege) jsonSerializer.encodeToJsonElement(it) else null + if (it is DrivingPrivilege) vckJsonSerializer.encodeToJsonElement(it) else null } } diff --git a/settings.gradle.kts b/settings.gradle.kts index a32ac70..58e2d9f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,6 +6,7 @@ pluginManagement { } mavenCentral() gradlePluginPortal() + maven("https://s01.oss.sonatype.org/content/repositories/snapshots") //KOTEST snapshot } } From cc0a02ac752a5235007a50d66917d64a8abeb82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Thu, 12 Sep 2024 19:09:13 +0200 Subject: [PATCH 03/13] react to vck api changes --- .../wallet/mdl/MobileDrivingLicenceJws.kt | 2 +- .../at/asitplus/wallet/mdl/IsoMdocTest.kt | 41 +++++-------------- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt index 67b5599..29b6fba 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt @@ -1,7 +1,7 @@ package at.asitplus.wallet.mdl import at.asitplus.KmmResult.Companion.wrap -import at.asitplus.wallet.lib.data.InstantLongSerializer +import at.asitplus.signum.indispensable.cosef.InstantLongSerializer import at.asitplus.wallet.lib.data.NullableInstantLongSerializer import at.asitplus.wallet.lib.data.jsonSerializer import kotlinx.datetime.Instant diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt index 9d4556a..41dbe04 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt @@ -3,28 +3,13 @@ package at.asitplus.wallet.mdl import at.asitplus.signum.indispensable.cosef.CoseHeader import at.asitplus.signum.indispensable.cosef.CoseKey import at.asitplus.signum.indispensable.cosef.CoseSigned +import at.asitplus.signum.indispensable.cosef.io.ByteStringWrapper +import at.asitplus.signum.indispensable.cosef.toCoseKey import at.asitplus.wallet.lib.agent.DefaultCryptoService -import at.asitplus.wallet.lib.agent.RandomKeyPairAdapter +import at.asitplus.wallet.lib.agent.EphemeralKeyWithoutCert import at.asitplus.wallet.lib.cbor.DefaultCoseService import at.asitplus.wallet.lib.cbor.DefaultVerifierCoseService -import at.asitplus.wallet.lib.iso.DeviceAuth -import at.asitplus.wallet.lib.iso.DeviceKeyInfo -import at.asitplus.wallet.lib.iso.DeviceRequest -import at.asitplus.wallet.lib.iso.DeviceResponse -import at.asitplus.wallet.lib.iso.DeviceSigned -import at.asitplus.wallet.lib.iso.DocRequest -import at.asitplus.wallet.lib.iso.Document -import at.asitplus.wallet.lib.iso.IssuerSigned -import at.asitplus.wallet.lib.iso.IssuerSignedItem -import at.asitplus.wallet.lib.iso.IssuerSignedList -import at.asitplus.wallet.lib.iso.ItemsRequest -import at.asitplus.wallet.lib.iso.ItemsRequestList -import at.asitplus.wallet.lib.iso.MobileSecurityObject -import at.asitplus.wallet.lib.iso.SingleItemsRequest -import at.asitplus.wallet.lib.iso.ValidityInfo -import at.asitplus.wallet.lib.iso.ValueDigest -import at.asitplus.wallet.lib.iso.ValueDigestList -import at.asitplus.wallet.lib.iso.sha256 +import at.asitplus.wallet.lib.iso.* import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DOCUMENT_NUMBER import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DRIVING_PRIVILEGES import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.EXPIRY_DATE @@ -36,13 +21,10 @@ import io.kotest.core.spec.style.FreeSpec import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe -import io.kotest.matchers.shouldNotBe import io.matthewnelson.encoding.base16.Base16 import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString import kotlinx.datetime.Clock import kotlinx.datetime.LocalDate -import at.asitplus.signum.indispensable.cosef.io.ByteStringWrapper -import at.asitplus.wallet.lib.agent.RandomKeyPairAdapter import kotlin.random.Random class IsoMdocTest : FreeSpec({ @@ -58,19 +40,18 @@ class IsoMdocTest : FreeSpec({ val verifierRequest = verifier.buildDeviceRequest() val walletResponse = wallet.buildDeviceResponse(verifierRequest) - issuer.cryptoService.keyPairAdapter.coseKey shouldNotBe null - verifier.verifyResponse(walletResponse, issuer.cryptoService.keyPairAdapter.coseKey) + verifier.verifyResponse(walletResponse, issuer.cryptoService.keyMaterial.publicKey.toCoseKey().getOrThrow()) } }) class Wallet { - val cryptoService = DefaultCryptoService(RandomKeyPairAdapter()) + val cryptoService = DefaultCryptoService(EphemeralKeyWithoutCert()) val coseService = DefaultCoseService(cryptoService) val deviceKeyInfo = DeviceKeyInfo( - deviceKey = cryptoService.keyPairAdapter.coseKey + deviceKey = cryptoService.keyMaterial.publicKey.toCoseKey().getOrThrow() ) var storedMdl: MobileDrivingLicence? = null @@ -150,7 +131,7 @@ class Wallet { class Issuer { - val cryptoService = DefaultCryptoService(RandomKeyPairAdapter()) + val cryptoService = DefaultCryptoService(EphemeralKeyWithoutCert()) val coseService = DefaultCoseService(cryptoService) suspend fun buildDeviceResponse(walletKeyInfo: DeviceKeyInfo): DeviceResponse { @@ -218,7 +199,7 @@ class Issuer { class Verifier { - val cryptoService = DefaultCryptoService(RandomKeyPairAdapter()) + val cryptoService = DefaultCryptoService(EphemeralKeyWithoutCert()) val coseService = DefaultCoseService(cryptoService) val verifierCoseService = DefaultVerifierCoseService() @@ -257,7 +238,7 @@ class Verifier { doc.errors.shouldBeNull() val issuerSigned = doc.issuerSigned val issuerAuth = issuerSigned.issuerAuth - verifierCoseService.verifyCose(issuerAuth, issuerKey).getOrThrow().shouldBe(true) + verifierCoseService.verifyCose(issuerAuth, issuerKey).isSuccess shouldBe true val issuerAuthPayload = issuerAuth.payload issuerAuthPayload.shouldNotBeNull() val mso = issuerSigned.getIssuerAuthPayloadAsMso() @@ -269,7 +250,7 @@ class Verifier { val walletKey = mso.deviceKeyInfo.deviceKey val deviceSignature = doc.deviceSigned.deviceAuth.deviceSignature deviceSignature.shouldNotBeNull() - verifierCoseService.verifyCose(deviceSignature, walletKey).getOrThrow().shouldBe(true) + verifierCoseService.verifyCose(deviceSignature, walletKey).isSuccess shouldBe true val namespaces = issuerSigned.namespaces namespaces.shouldNotBeNull() val issuerSignedItems = namespaces[MobileDrivingLicenceScheme.isoNamespace] From 82dab4929badbab7bb73383597319d9676f0165f Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Wed, 25 Sep 2024 15:09:21 +0200 Subject: [PATCH 04/13] Uncomment tests after fixes in vck --- .../wallet/mdl/CborSerializationTest.kt | 68 ++++++++--------- .../at/asitplus/wallet/mdl/IsoMdocTest.kt | 76 +++++++------------ 2 files changed, 58 insertions(+), 86 deletions(-) diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt index 4cb428a..af7d27e 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt @@ -2,19 +2,13 @@ package at.asitplus.wallet.mdl import at.asitplus.signum.indispensable.cosef.CoseSigned import at.asitplus.wallet.lib.data.jsonSerializer -import at.asitplus.wallet.lib.iso.DeviceRequest -import at.asitplus.wallet.lib.iso.DeviceResponse -import at.asitplus.wallet.lib.iso.IssuerSignedItem -import at.asitplus.wallet.lib.iso.IssuerSignedList -import at.asitplus.wallet.lib.iso.ItemsRequestList +import at.asitplus.wallet.lib.iso.* import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DOCUMENT_NUMBER import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DRIVING_PRIVILEGES import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.EXPIRY_DATE import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.FAMILY_NAME import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.ISSUE_DATE import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.PORTRAIT -import at.asitplus.wallet.lib.iso.MobileSecurityObject -import at.asitplus.wallet.lib.iso.ValueDigestList import io.kotest.core.spec.style.FreeSpec import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.nulls.shouldNotBeNull @@ -30,7 +24,6 @@ import kotlin.random.Random class CborSerializationTest : FreeSpec({ - "mDL" { val mdl = MobileDrivingLicence( familyName = "Mustermann", @@ -52,7 +45,7 @@ class CborSerializationTest : FreeSpec({ unDistinguishingSign = "AT" ) - val serialized = mdl.serialize().encodeToString(Base16(strict = true)).uppercase() + val serialized = mdl.serialize().encodeToString(Base16(true)).uppercase() println(serialized) serialized shouldContain "76656869636C655F63617465676F72795F636F6465" // "vehicle_category_code" @@ -139,7 +132,7 @@ class CborSerializationTest : FreeSpec({ 9bb7f80bf """.trimIndent().replace("\n", "").uppercase() - val deviceRequest = DeviceRequest.deserialize(input.decodeToByteArray(Base16(strict = true))) + val deviceRequest = DeviceRequest.deserialize(input.decodeToByteArray(Base16(true))) .getOrThrow().shouldNotBeNull() println(deviceRequest) @@ -159,7 +152,7 @@ class CborSerializationTest : FreeSpec({ docRequest.readerAuth.shouldNotBeNull() docRequest.readerAuth?.unprotectedHeader?.certificateChain?.shouldNotBeNull() - deviceRequest.serialize().encodeToString(Base16(strict = true)).uppercase() shouldBe input + deviceRequest.serialize().encodeToString(Base16(true)).uppercase() shouldBe input } // From ISO/IEC 18013-5:2021(E), D4.1.2, page 116 @@ -326,7 +319,7 @@ class CborSerializationTest : FreeSpec({ 806a07f8b5388a332d92c189a7bf293ee1f543405ae6824d6673746174757300 """.trimIndent().replace("\n", "").uppercase() - val deviceResponse = DeviceResponse.deserialize(input.decodeToByteArray(Base16(strict = true))) + val deviceResponse = DeviceResponse.deserialize(input.decodeToByteArray(Base16(true))) .getOrThrow().shouldNotBeNull() println(deviceResponse) @@ -360,8 +353,8 @@ class CborSerializationTest : FreeSpec({ issueDate = LocalDate.parse("2017-02-23"), expiryDate = LocalDate.parse("2024-10-20") ) - val mso = document.issuerSigned.getIssuerAuthPayloadAsMso() - mso.shouldNotBeNull() + val mso = document.issuerSigned.getIssuerAuthPayloadAsMso().getOrThrow() + mso.version shouldBe "1.0" mso.digestAlgorithm shouldBe "SHA-256" mso.docType shouldBe MobileDrivingLicenceScheme.isoDocType @@ -371,19 +364,19 @@ class CborSerializationTest : FreeSpec({ val valueDigestList = mso.valueDigests[MobileDrivingLicenceScheme.isoNamespace] valueDigestList.shouldNotBeNull() valueDigestList.findItem(0U) shouldBe "75167333B47B6C2BFB86ECCC1F438CF57AF055371AC55E1E359E20F254ADCEBF" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) valueDigestList.findItem(1U) shouldBe "67E539D6139EBD131AEF441B445645DD831B2B375B390CA5EF6279B205ED4571" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) val valueDigestListUs = mso.valueDigests["${MobileDrivingLicenceScheme.isoNamespace}.US"] valueDigestListUs.shouldNotBeNull() valueDigestListUs.findItem(0U) shouldBe "D80B83D25173C484C5640610FF1A31C949C1D934BF4CF7F18D5223B15DD4F21C" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) valueDigestListUs.findItem(1U) shouldBe "4D80E1E2E4FB246D97895427CE7000BB59BB24C8CD003ECF94BF35BBD2917E34" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) document.deviceSigned.deviceAuth.deviceMac.shouldNotBeNull() - deviceResponse.serialize().encodeToString(Base16(strict = true)) shouldBe input + deviceResponse.serialize().encodeToString(Base16(true)) shouldBe input } "Driving Privilege" { @@ -393,7 +386,7 @@ class CborSerializationTest : FreeSpec({ expiryDate = LocalDate.parse("2024-10-20") ) - val serialized = drivingPrivilege.serialize().encodeToString(Base16(strict = true)).uppercase() + val serialized = drivingPrivilege.serialize().encodeToString(Base16(true)).uppercase() println(serialized) serialized shouldContain "76656869636C655F63617465676F72795F636F6465" // "vehicle_category_code" @@ -408,7 +401,7 @@ class CborSerializationTest : FreeSpec({ val input = "a37576656869636c655f63617465676f72795f636f646561416a69737375655f64617465d903ec6a323031382d30382d" + "30396b6578706972795f64617465d903ec6a323032342d31302d3230" - val deserialized = DrivingPrivilege.deserialize(input.uppercase().decodeToByteArray(Base16(strict = true))) + val deserialized = DrivingPrivilege.deserialize(input.uppercase().decodeToByteArray(Base16(true))) .getOrThrow().shouldNotBeNull() deserialized.vehicleCategoryCode shouldBe "A" @@ -417,18 +410,18 @@ class CborSerializationTest : FreeSpec({ } - "!Date in IssuerSignedItem from ISO example" { + "Date in IssuerSignedItem from ISO example" { val input = """ a4686469676573744944036672616e646f6d5820b23f627e8999c706df0c0a4ed98ad74af988af619b4bb078b89058553f44615d7165 6c656d656e744964656e7469666965726a69737375655f646174656c656c656d656e7456616c7565d903ec6a323031392d31302d3230 """.trimIndent().replace("\n", "").uppercase() - // val deserialized = IssuerSignedItem.deserialize(input.decodeToByteArray(Base16(strict = true))) - // .getOrThrow().shouldNotBeNull() - // val serialized = deserialized.serialize() + val inputDecoded = input.decodeToByteArray(Base16(true)) + val deserialized = IssuerSignedItem.deserialize(inputDecoded, MobileDrivingLicenceScheme.isoNamespace) + .getOrThrow().shouldNotBeNull() + val serialized = deserialized.serialize(MobileDrivingLicenceScheme.isoNamespace) - // TODO "elementValue" in IssuerSignedItem needs a tag 1004u (0xD903EC) iff the value is a date - // serialized.encodeToString(Base16(strict = true)).uppercase() shouldBe input + serialized.encodeToString(Base16(true)).uppercase() shouldBe input } "Driving Privilege in IssuerSignedItem from ISO example" { @@ -487,11 +480,12 @@ class CborSerializationTest : FreeSpec({ 03EC6A323031372D30322D32336B6578706972795F64617465D903EC6A323032342D31302D3230 """.trimIndent().replace("\n", "") - // val deserialized = IssuerSignedItem.deserialize(input.decodeToByteArray(Base16(strict = true))) - // .getOrThrow().shouldNotBeNull() - // val serialized = deserialized.serialize() + val inputDecoded = input.decodeToByteArray(Base16(true)) + val deserialized = IssuerSignedItem.deserialize(inputDecoded, MobileDrivingLicenceScheme.isoNamespace) + .getOrThrow().shouldNotBeNull() + val serialized = deserialized.serialize(MobileDrivingLicenceScheme.isoNamespace) - // serialized.encodeToString(Base16(strict = true)).uppercase() shouldBe input + serialized.encodeToString(Base16(true)).uppercase() shouldBe input } // From ISO/IEC 18013-5:2021(E), page 130 @@ -604,7 +598,7 @@ class CborSerializationTest : FreeSpec({ 044b890ad85aa53f129134775d733754d7cb7a413766aeff13cb2e """.trimIndent().replace("\n", "").uppercase() - val coseSigned = CoseSigned.deserialize(input.decodeToByteArray(Base16(strict = true))).getOrThrow() + val coseSigned = CoseSigned.deserialize(input.decodeToByteArray(Base16(true))).getOrThrow() println(coseSigned) val payload = coseSigned.payload @@ -620,17 +614,17 @@ class CborSerializationTest : FreeSpec({ val valueDigestList = mso.valueDigests[MobileDrivingLicenceScheme.isoNamespace] valueDigestList.shouldNotBeNull() valueDigestList.findItem(0U) shouldBe "75167333B47B6C2BFB86ECCC1F438CF57AF055371AC55E1E359E20F254ADCEBF" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) valueDigestList.findItem(1U) shouldBe "67E539D6139EBD131AEF441B445645DD831B2B375B390CA5EF6279B205ED4571" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) val valueDigestListUs = mso.valueDigests["${MobileDrivingLicenceScheme.isoNamespace}.US"] valueDigestListUs.shouldNotBeNull() valueDigestListUs.findItem(0U) shouldBe "D80B83D25173C484C5640610FF1A31C949C1D934BF4CF7F18D5223B15DD4F21C" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) valueDigestListUs.findItem(1U) shouldBe "4D80E1E2E4FB246D97895427CE7000BB59BB24C8CD003ECF94BF35BBD2917E34" - .decodeToByteArray(Base16(strict = true)) + .decodeToByteArray(Base16(true)) - coseSigned.serialize().encodeToString(Base16(strict = true)) shouldBe input + coseSigned.serialize().encodeToString(Base16(true)) shouldBe input } }) diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt index 41dbe04..c2552e0 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt @@ -21,6 +21,7 @@ import io.kotest.core.spec.style.FreeSpec import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf import io.matthewnelson.encoding.base16.Base16 import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString import kotlinx.datetime.Clock @@ -34,7 +35,6 @@ class IsoMdocTest : FreeSpec({ val verifier = Verifier() val issuer = Issuer() - // TODO Wallet needs to prove possession of key val deviceResponse = issuer.buildDeviceResponse(wallet.deviceKeyInfo) wallet.storeMdl(deviceResponse) @@ -59,21 +59,17 @@ class Wallet { var storedMdlItems: IssuerSignedList? = null fun storeMdl(deviceResponse: DeviceResponse) { - val document = deviceResponse.documents?.firstOrNull() - document.shouldNotBeNull() + val document = deviceResponse.documents?.first().shouldNotBeNull() document.docType shouldBe MobileDrivingLicenceScheme.isoDocType val issuerAuth = document.issuerSigned.issuerAuth this.storedIssuerAuth = issuerAuth - println("Wallet stored IssuerAuth: $issuerAuth") - val issuerAuthPayload = issuerAuth.payload - issuerAuthPayload.shouldNotBeNull() - val mso = document.issuerSigned.getIssuerAuthPayloadAsMso() - mso.shouldNotBeNull() - val mdlItems = document.issuerSigned.namespaces?.get(MobileDrivingLicenceScheme.isoNamespace) - mdlItems.shouldNotBeNull() + + issuerAuth.payload.shouldNotBeNull() + val mso = document.issuerSigned.getIssuerAuthPayloadAsMso().getOrThrow() + + val mdlItems = document.issuerSigned.namespaces?.get(MobileDrivingLicenceScheme.isoNamespace).shouldNotBeNull() this.storedMdlItems = mdlItems - val valueDigests = mso.valueDigests[MobileDrivingLicenceScheme.isoNamespace] - valueDigests.shouldNotBeNull() + mso.valueDigests[MobileDrivingLicenceScheme.isoNamespace].shouldNotBeNull() val givenNameValue = extractDataString(mdlItems, GIVEN_NAME) val familyNameValue = extractDataString(mdlItems, FAMILY_NAME) @@ -91,20 +87,18 @@ class Wallet { expiryDate = LocalDate.parse(expiryDateValue), drivingPrivileges = drivingPrivilegesValue.toList(), ) - println("Wallet stored MDL: $storedMdl") } suspend fun buildDeviceResponse(verifierRequest: DeviceRequest): DeviceResponse { - val isoNamespace = - verifierRequest.docRequests[0].itemsRequest.value.namespaces[MobileDrivingLicenceScheme.isoNamespace] - isoNamespace.shouldNotBeNull() + val itemsRequest = verifierRequest.docRequests[0].itemsRequest + val isoNamespace = itemsRequest.value.namespaces[MobileDrivingLicenceScheme.isoNamespace].shouldNotBeNull() val requestedKeys = isoNamespace.entries.filter { it.value }.map { it.key } return DeviceResponse( version = "1.0", documents = arrayOf( Document( docType = MobileDrivingLicenceScheme.isoDocType, - issuerSigned = IssuerSigned( + issuerSigned = IssuerSigned.fromIssuerSignedItems( namespacedItems = mapOf( MobileDrivingLicenceScheme.isoNamespace to storedMdlItems!!.entries.filter { it.value.elementIdentifier in requestedKeys @@ -113,7 +107,7 @@ class Wallet { issuerAuth = storedIssuerAuth!! ), deviceSigned = DeviceSigned( - namespaces = byteArrayOf(), + namespaces = ByteStringWrapper(DeviceNameSpaces(mapOf())), deviceAuth = DeviceAuth( deviceSignature = coseService.createSignedCose( payload = null, @@ -174,11 +168,9 @@ class Issuer { documents = arrayOf( Document( docType = MobileDrivingLicenceScheme.isoDocType, - issuerSigned = IssuerSigned( + issuerSigned = IssuerSigned.fromIssuerSignedItems( namespacedItems = mapOf( - MobileDrivingLicenceScheme.isoNamespace to - issuerSigned - + MobileDrivingLicenceScheme.isoNamespace to issuerSigned ), issuerAuth = coseService.createSignedCose( payload = mso.serializeForIssuerAuth(), @@ -187,7 +179,7 @@ class Issuer { ).getOrThrow() ), deviceSigned = DeviceSigned( - namespaces = byteArrayOf(), + namespaces = ByteStringWrapper(DeviceNameSpaces(mapOf())), deviceAuth = DeviceAuth() ) ) @@ -231,30 +223,24 @@ class Verifier { ) fun verifyResponse(deviceResponse: DeviceResponse, issuerKey: CoseKey) { - val documents = deviceResponse.documents - documents.shouldNotBeNull() + val documents = deviceResponse.documents.shouldNotBeNull() val doc = documents.first() doc.docType shouldBe MobileDrivingLicenceScheme.isoDocType doc.errors.shouldBeNull() val issuerSigned = doc.issuerSigned val issuerAuth = issuerSigned.issuerAuth verifierCoseService.verifyCose(issuerAuth, issuerKey).isSuccess shouldBe true - val issuerAuthPayload = issuerAuth.payload - issuerAuthPayload.shouldNotBeNull() - val mso = issuerSigned.getIssuerAuthPayloadAsMso() - mso.shouldNotBeNull() + issuerAuth.payload.shouldNotBeNull() + val mso = issuerSigned.getIssuerAuthPayloadAsMso().getOrThrow() + mso.docType shouldBe MobileDrivingLicenceScheme.isoDocType - val mdlItems = mso.valueDigests[MobileDrivingLicenceScheme.isoNamespace] - mdlItems.shouldNotBeNull() + val mdlItems = mso.valueDigests[MobileDrivingLicenceScheme.isoNamespace].shouldNotBeNull() val walletKey = mso.deviceKeyInfo.deviceKey - val deviceSignature = doc.deviceSigned.deviceAuth.deviceSignature - deviceSignature.shouldNotBeNull() + val deviceSignature = doc.deviceSigned.deviceAuth.deviceSignature.shouldNotBeNull() verifierCoseService.verifyCose(deviceSignature, walletKey).isSuccess shouldBe true - val namespaces = issuerSigned.namespaces - namespaces.shouldNotBeNull() - val issuerSignedItems = namespaces[MobileDrivingLicenceScheme.isoNamespace] - issuerSignedItems.shouldNotBeNull() + val namespaces = issuerSigned.namespaces.shouldNotBeNull() + val issuerSignedItems = namespaces[MobileDrivingLicenceScheme.isoNamespace].shouldNotBeNull() extractAndVerifyData(issuerSignedItems, mdlItems, FAMILY_NAME) extractAndVerifyData(issuerSignedItems, mdlItems, GIVEN_NAME) @@ -266,13 +252,10 @@ class Verifier { key: String ) { val issuerSignedItem = issuerSignedItems.entries.first { it.value.elementIdentifier == key } - val elementValue = issuerSignedItem.value.elementValue.toString() - elementValue.shouldNotBeNull() - val issuerHash = mdlItems.entries.first { it.key == issuerSignedItem.value.digestId } - issuerHash.shouldNotBeNull() + //val elementValue = issuerSignedItem.value.elementValue.toString().shouldNotBeNull() + val issuerHash = mdlItems.entries.first { it.key == issuerSignedItem.value.digestId }.shouldNotBeNull() val verifierHash = issuerSignedItem.serialized.sha256() verifierHash.encodeToString(Base16(strict = true)) shouldBe issuerHash.value.encodeToString(Base16(strict = true)) - println("Verifier got $key with value $elementValue and correct hash ${verifierHash.encodeToString(Base16(strict = true))}") } } @@ -281,9 +264,7 @@ private fun extractDataString( key: String ): String { val element = mdlItems.entries.first { it.value.elementIdentifier == key } - val value = element.value.elementValue.toString() - value.shouldNotBeNull() - return value + return element.value.elementValue.toString().shouldNotBeNull() } private fun extractDataDrivingPrivileges( @@ -291,12 +272,9 @@ private fun extractDataDrivingPrivileges( key: String ): Array { val element = mdlItems.entries.first { it.value.elementIdentifier == key } - val value = element.value.elementValue as Array - value.shouldNotBeNull() - return value + return element.value.elementValue.shouldBeInstanceOf>() } - fun buildIssuerSignedItem(elementIdentifier: String, elementValue: Any, digestId: UInt) = IssuerSignedItem( digestId = digestId, random = Random.nextBytes(16), From 80aa1b88d640723184f3627eac259ebf36ed572a Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Thu, 26 Sep 2024 10:01:38 +0200 Subject: [PATCH 05/13] Remove composite build --- build.gradle.kts | 2 +- settings.gradle.kts | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2b6230b..c3e2e2b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("at.asitplus.gradle.conventions") version "2.0.0+20240905" + id("at.asitplus.gradle.conventions") version "2.0.0+20240920" } val artifactVersion: String by extra diff --git a/settings.gradle.kts b/settings.gradle.kts index 58e2d9f..6a1e8ca 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,13 +10,5 @@ pluginManagement { } } -includeBuild("..") { - dependencySubstitution { - substitute(module("at.asitplus.wallet:vck")).using(project(":vck")) - substitute(module("at.asitplus.wallet:vck-openid")).using(project(":vck-openid")) - substitute(module("at.asitplus.wallet:vck-aries")).using(project(":vck-aries")) - } -} - rootProject.name = "mobile-driving-licence" include(":mobiledrivinglicence") From c10d54156559d9c42f8e16b67695eb9843b72ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Thu, 26 Sep 2024 10:04:44 +0200 Subject: [PATCH 06/13] fix conventions version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index c3e2e2b..d6e3049 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("at.asitplus.gradle.conventions") version "2.0.0+20240920" + id("at.asitplus.gradle.conventions") version "2.0.20+20240920" } val artifactVersion: String by extra From 0f0cdb54e1b3fa6efd4329b10df57608d9bb2b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Thu, 26 Sep 2024 10:21:12 +0200 Subject: [PATCH 07/13] Try latest SANPSHOT VC-K --- mobiledrivinglicence/build.gradle.kts | 2 +- .../src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt | 2 +- .../kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mobiledrivinglicence/build.gradle.kts b/mobiledrivinglicence/build.gradle.kts index 39f3638..b19a067 100644 --- a/mobiledrivinglicence/build.gradle.kts +++ b/mobiledrivinglicence/build.gradle.kts @@ -25,7 +25,7 @@ kotlin { sourceSets { commonMain { dependencies { - api("at.asitplus.wallet:vck:4.1.0") + api("at.asitplus.wallet:vck:5.0.0-SNAPSHOT") } } } diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt index c2552e0..d4f893c 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt @@ -151,7 +151,7 @@ class Issuer { digestAlgorithm = "SHA-256", valueDigests = mapOf( MobileDrivingLicenceScheme.isoNamespace to ValueDigestList(entries = issuerSigned.map { - ValueDigest.fromIssuerSigned(MobileDrivingLicenceScheme.isoNamespace, it) + ValueDigest.fromIssuerSignedItem(it, MobileDrivingLicenceScheme.isoNamespace) }) ), deviceKeyInfo = walletKeyInfo, diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt index 35bbe5f..7e02b7b 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt @@ -140,7 +140,7 @@ class JsonSerializationTest : FreeSpec({ println(serverResponse) val payload = serverResponse.documents.first() - val jws = JwsSigned.parse(payload).getOrThrow() + val jws = JwsSigned.deserialize(payload).getOrThrow() val mdlJws = MobileDrivingLicenceJws.deserialize(jws.payload.decodeToString()).getOrThrow().shouldNotBeNull() println(mdlJws) From 23b0f2256e68f3a1febbddb761f323082f25b65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Fri, 27 Sep 2024 16:56:46 +0200 Subject: [PATCH 08/13] update changelog --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 90c5e36..63b0c41 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ These attributes are implemented: ## Changelog +Release 1.1.0: +- Proper deserialization handling +- Update to VC-K 5.0.0 + Release 1.0.3: - Rename `Initializer.initWithVck` to `Initializer.initWithVCK` From 471f1489024701256ccd7cfc997c33a5430be6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Fri, 27 Sep 2024 17:09:10 +0200 Subject: [PATCH 09/13] fix kotlin badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63b0c41..ef6b141 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Powered by VC-K](https://img.shields.io/badge/VC--K-powered-8A2BE2?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4LjAzIDkuNSI+PGcgZmlsbD0iIzhhMmJlMiIgZm9udC1mYW1pbHk9IlZBTE9SQU5UIiBmb250LXNpemU9IjEyLjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPjxwYXRoIGQ9Ik01OS42NCAyMjIuMTNxMC0uOTguMzYtMS44Mi4zNy0uODQuOTgtMS40Ni42Mi0uNjIgMS40Ni0uOTYuODMtLjM2IDEuOC0uMzUgMS4wMy4wMiAxLjkuNDIuODcuNCAxLjUgMS4xMi4wNC4wNS4wMy4xMSAwIC4wNy0uMDUuMWwtMSAuODZxLS4wNi4wMy0uMTIuMDN0LS4xLS4wNnEtLjQyLS40OC0xLS43Ni0uNTYtLjMtMS4yMi0uMjgtLjYuMDEtMS4xMy4yNy0uNTQuMjQtLjkzLjY3LS40LjQyLS42Mi45OC0uMjMuNTYtLjIzIDEuMiAwIC42My4yNCAxLjE4LjI0LjU2LjY1Ljk4LjQuNDIuOTQuNjYuNTMuMjMgMS4xNC4yMy42My0uMDEgMS4yLS4zLjU1LS4yNy45Ni0uNzUuMDQtLjA1LjEtLjA1LjA2LS4wMi4xMS4wM2wxIC44NnEuMDYuMDMuMDYuMS4wMS4wNi0uMDMuMTEtLjY0LjczLTEuNTMgMS4xNC0uOS40MS0xLjk1LjQtLjk1IDAtMS43OS0uMzYtLjgyLS4zNy0xLjQzLS45OS0uNjEtLjYzLS45NS0xLjQ4LS4zNS0uODUtLjM1LTEuODN6IiBzdHlsZT0iLWlua3NjYXBlLWZvbnQtc3BlY2lmaWNhdGlvbjpWQUxPUkFOVDt0ZXh0LWFsaWduOmNlbnRlciIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTU5LjY0IC0yMTcuNDIpIi8+PHBhdGggZD0iTTY2LjIxIDIyMS4zNWgxLjNjLjEgMCAuMTYuMDYuMTYuMTd2MS4zOGMwIC4xMS0uMDUuMTctLjE2LjE3aC0xLjNjLS4xIDAtLjE2LS4wNi0uMTYtLjE3di0xLjM4YzAtLjExLjA1LS4xNy4xNi0uMTd6IiBsZXR0ZXItc3BhY2luZz0iLTMuMTIiIHN0eWxlPSItaW5rc2NhcGUtZm9udC1zcGVjaWZpY2F0aW9uOlZBTE9SQU5UO3RleHQtYWxpZ246Y2VudGVyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTkuNjQgLTIxNy40MikiLz48L2c+PC9zdmc+&logoColor=white&labelColor=white)](https://github.com/a-sit-plus/vck) [![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-brightgreen.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0) [![Kotlin](https://img.shields.io/badge/kotlin-multiplatform--mobile-orange.svg?logo=kotlin)](http://kotlinlang.org) -[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0-blue.svg?logo=kotlin)](http://kotlinlang.org) +[![Kotlin](https://img.shields.io/badge/kotlin-2.0.20-blue.svg?logo=kotlin)](http://kotlinlang.org) ![Java](https://img.shields.io/badge/java-17-blue.svg?logo=OPENJDK) [![Maven Central](https://img.shields.io/maven-central/v/at.asitplus.wallet/mobiledrivinglicence)](https://mvnrepository.com/artifact/at.asitplus.wallet/mobiledrivinglicence/) From f84f3b256c3c62f135f2ce9c4133164d68377f29 Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Mon, 30 Sep 2024 11:21:55 +0200 Subject: [PATCH 10/13] Move test to correct class --- .../at/asitplus/wallet/mdl/Initializer.kt | 2 +- .../wallet/mdl/CborSerializationTest.kt | 38 +------------------ .../wallet/mdl/JsonSerializationTest.kt | 33 ++++++++++++++-- 3 files changed, 32 insertions(+), 41 deletions(-) diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt index 7063f89..3137635 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt @@ -45,7 +45,7 @@ object Initializer { MobileDrivingLicenceDataElements.AGE_IN_YEARS to UInt.serializer(), MobileDrivingLicenceDataElements.AGE_BIRTH_YEAR to UInt.serializer(), MobileDrivingLicenceDataElements.SIGNATURE_USUAL_MARK to ByteArraySerializer(), - ) + ) ) } diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt index af7d27e..96a4f39 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt @@ -1,7 +1,6 @@ package at.asitplus.wallet.mdl import at.asitplus.signum.indispensable.cosef.CoseSigned -import at.asitplus.wallet.lib.data.jsonSerializer import at.asitplus.wallet.lib.iso.* import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DOCUMENT_NUMBER import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DRIVING_PRIVILEGES @@ -19,7 +18,6 @@ import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArray import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString import kotlinx.datetime.Instant import kotlinx.datetime.LocalDate -import kotlinx.serialization.encodeToString import kotlin.random.Random class CborSerializationTest : FreeSpec({ @@ -42,11 +40,10 @@ class CborSerializationTest : FreeSpec({ expiryDate = LocalDate.parse("2024-10-20") ) ), - unDistinguishingSign = "AT" + unDistinguishingSign = "AT", ) val serialized = mdl.serialize().encodeToString(Base16(true)).uppercase() - println(serialized) serialized shouldContain "76656869636C655F63617465676F72795F636F6465" // "vehicle_category_code" serialized shouldContain "69737375655F64617465" // "issue_date" @@ -55,33 +52,6 @@ class CborSerializationTest : FreeSpec({ serialized shouldContain "6578706972795" // "2024-10-20" } - "mDL as JSON" { - val mdl = MobileDrivingLicence( - familyName = "Mustermann", - givenName = "Max", - dateOfBirth = LocalDate.parse("1970-01-01"), - issueDate = LocalDate.parse("2018-08-09"), - expiryDate = LocalDate.parse("2024-10-20"), - issuingCountry = "AT", - issuingAuthority = "LPD Steiermark", - licenceNumber = "A/3f984/019", - portrait = Random.nextBytes(16), - drivingPrivileges = listOf( - DrivingPrivilege( - vehicleCategoryCode = "A", - issueDate = LocalDate.parse("2018-08-09"), - expiryDate = LocalDate.parse("2024-10-20") - ) - ), - unDistinguishingSign = "AT" - ) - - val serialized = jsonSerializer.encodeToString(mdl) - println(serialized) - - serialized shouldContain "LPD Steiermark" - } - // From ISO/IEC 18013-5:2021(E), D4.1.1, page 115 "mdoc request" { /** @@ -134,7 +104,6 @@ class CborSerializationTest : FreeSpec({ val deviceRequest = DeviceRequest.deserialize(input.decodeToByteArray(Base16(true))) .getOrThrow().shouldNotBeNull() - println(deviceRequest) deviceRequest.version shouldBe "1.0" val docRequest = deviceRequest.docRequests.first() @@ -322,8 +291,6 @@ class CborSerializationTest : FreeSpec({ val deviceResponse = DeviceResponse.deserialize(input.decodeToByteArray(Base16(true))) .getOrThrow().shouldNotBeNull() - println(deviceResponse) - deviceResponse.version shouldBe "1.0" val document = deviceResponse.documents?.get(0) document.shouldNotBeNull() @@ -387,7 +354,6 @@ class CborSerializationTest : FreeSpec({ ) val serialized = drivingPrivilege.serialize().encodeToString(Base16(true)).uppercase() - println(serialized) serialized shouldContain "76656869636C655F63617465676F72795F636F6465" // "vehicle_category_code" serialized shouldContain "69737375655F64617465" // "issue_date" @@ -599,12 +565,10 @@ class CborSerializationTest : FreeSpec({ """.trimIndent().replace("\n", "").uppercase() val coseSigned = CoseSigned.deserialize(input.decodeToByteArray(Base16(true))).getOrThrow() - println(coseSigned) val payload = coseSigned.payload payload.shouldNotBeNull() val mso = MobileSecurityObject.deserializeFromIssuerAuth(payload).getOrThrow().shouldNotBeNull() - println(mso) mso.version shouldBe "1.0" mso.digestAlgorithm shouldBe "SHA-256" mso.docType shouldBe MobileDrivingLicenceScheme.isoDocType diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt index 7e02b7b..9c8d8f1 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt @@ -1,6 +1,7 @@ package at.asitplus.wallet.mdl import at.asitplus.signum.indispensable.josef.JwsSigned +import at.asitplus.wallet.lib.data.vckJsonSerializer import at.asitplus.wallet.lib.iso.ServerRequest import at.asitplus.wallet.lib.iso.ServerResponse import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DOCUMENT_NUMBER @@ -14,7 +15,10 @@ import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain import kotlinx.datetime.LocalDate +import kotlinx.serialization.encodeToString +import kotlin.random.Random class JsonSerializationTest : FreeSpec({ @@ -42,7 +46,6 @@ class JsonSerializationTest : FreeSpec({ """.trimIndent() val serverRequest = ServerRequest.deserialize(input).getOrThrow().shouldNotBeNull() - println(serverRequest) serverRequest.version shouldBe "1.0" val docRequest = serverRequest.docRequests[0] @@ -57,6 +60,32 @@ class JsonSerializationTest : FreeSpec({ itemRequests[PORTRAIT] shouldBe false } + "mDL as JSON" { + val mdl = MobileDrivingLicence( + familyName = "Mustermann", + givenName = "Max", + dateOfBirth = LocalDate.parse("1970-01-01"), + issueDate = LocalDate.parse("2018-08-09"), + expiryDate = LocalDate.parse("2024-10-20"), + issuingCountry = "AT", + issuingAuthority = "LPD Steiermark", + licenceNumber = "A/3f984/019", + portrait = Random.nextBytes(16), + drivingPrivileges = listOf( + DrivingPrivilege( + vehicleCategoryCode = "A", + issueDate = LocalDate.parse("2018-08-09"), + expiryDate = LocalDate.parse("2024-10-20") + ) + ), + unDistinguishingSign = "AT" + ) + + val serialized = vckJsonSerializer.encodeToString(mdl) + + serialized shouldContain "LPD Steiermark" + } + // from ISO/IEC 18013-5:2021(E), D4.2.1.2, page 121 "Server Response" { /** @@ -137,13 +166,11 @@ class JsonSerializationTest : FreeSpec({ """.trimIndent() val serverResponse = ServerResponse.deserialize(input).getOrThrow().shouldNotBeNull() - println(serverResponse) val payload = serverResponse.documents.first() val jws = JwsSigned.deserialize(payload).getOrThrow() val mdlJws = MobileDrivingLicenceJws.deserialize(jws.payload.decodeToString()).getOrThrow().shouldNotBeNull() - println(mdlJws) mdlJws.doctype shouldBe MobileDrivingLicenceScheme.isoDocType val mdl = mdlJws.namespaces.mdl From e6665ded2ddd51b6d6179388fa555ed964ee0480 Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Mon, 30 Sep 2024 12:00:46 +0200 Subject: [PATCH 11/13] Test serialization and de-serialization --- .../at/asitplus/wallet/mdl/Initializer.kt | 35 --------- .../wallet/mdl/SerializerRegistrationTest.kt | 72 +++++++++++++++++++ 2 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt index 3137635..6c8b1b5 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt @@ -1,16 +1,12 @@ package at.asitplus.wallet.mdl -import at.asitplus.wallet.lib.ItemValueEncoder import at.asitplus.wallet.lib.JsonValueEncoder import at.asitplus.wallet.lib.LibraryInitializer -import at.asitplus.wallet.lib.SerializerLookup import at.asitplus.wallet.lib.data.vckJsonSerializer import kotlinx.datetime.LocalDate import kotlinx.serialization.builtins.ArraySerializer import kotlinx.serialization.builtins.ByteArraySerializer import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.CompositeEncoder import kotlinx.serialization.json.encodeToJsonElement object Initializer { @@ -29,8 +25,6 @@ object Initializer { fun initWithVCK() { LibraryInitializer.registerExtensionLibrary( credentialScheme = MobileDrivingLicenceScheme, - serializerLookup = serializerLookup(), - itemValueEncoder = itemValueEncoder(), jsonValueEncoder = jsonValueEncoder(), itemValueDecoderMap = mapOf( MobileDrivingLicenceDataElements.BIRTH_DATE to LocalDate.serializer(), @@ -49,35 +43,6 @@ object Initializer { ) } - private fun serializerLookup(): SerializerLookup = { - if (it is Array<*>) ArraySerializer(DrivingPrivilege.serializer()) else null - } - - private fun itemValueEncoder(): ItemValueEncoder = { descriptor, index, compositeEncoder, value -> - if (value is Array<*> && value.isNotEmpty() && value.all { it is DrivingPrivilege }) { - true.also { - encodeArrayOfDrivingPrivileges(compositeEncoder, descriptor, index, value) - } - } else { - false - } - } - - @Suppress("UNCHECKED_CAST") - private fun encodeArrayOfDrivingPrivileges( - compositeEncoder: CompositeEncoder, - descriptor: SerialDescriptor, - index: Int, - value: Any - ) { - compositeEncoder.encodeSerializableElement( - descriptor, - index, - ArraySerializer(DrivingPrivilege.serializer()), - value as Array - ) - } - private fun jsonValueEncoder(): JsonValueEncoder = { if (it is DrivingPrivilege) vckJsonSerializer.encodeToJsonElement(it) else null } diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt new file mode 100644 index 0000000..afb8e9b --- /dev/null +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt @@ -0,0 +1,72 @@ +package at.asitplus.wallet.mdl + +import at.asitplus.wallet.lib.iso.IssuerSignedItem +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.AGE_BIRTH_YEAR +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.AGE_IN_YEARS +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.BIRTH_DATE +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.DRIVING_PRIVILEGES +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.EXPIRY_DATE +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.HEIGHT +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.ISSUE_DATE +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.PORTRAIT +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.PORTRAIT_CAPTURE_DATE +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.SEX +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.SIGNATURE_USUAL_MARK +import at.asitplus.wallet.mdl.MobileDrivingLicenceDataElements.WEIGHT +import io.kotest.core.spec.style.FreeSpec +import io.kotest.datatest.withData +import io.kotest.matchers.shouldBe +import kotlinx.datetime.LocalDate +import kotlin.random.Random +import kotlin.random.nextUInt + +class SerializerRegistrationTest : FreeSpec({ + + "Serialization and deserialization" - { + withData( + nameFn = { + "for ${it.key}" + }, + dataMap().entries + ) { + val item = IssuerSignedItem( + digestId = Random.nextUInt(), + random = Random.nextBytes(32), + elementIdentifier = it.key, + elementValue = it.value + ) + + val serialized = item.serialize(MobileDrivingLicenceScheme.isoNamespace) + + val deserialized = + IssuerSignedItem.deserialize(serialized, MobileDrivingLicenceScheme.isoNamespace).getOrThrow() + + deserialized.elementValue shouldBe it.value + } + } + +}) + +private fun dataMap(): Map = + mapOf( + BIRTH_DATE to randomLocalDate(), + ISSUE_DATE to randomLocalDate(), + EXPIRY_DATE to randomLocalDate(), + PORTRAIT to Random.nextBytes(32), + DRIVING_PRIVILEGES to listOf( + DrivingPrivilege( + vehicleCategoryCode = "A", + issueDate = randomLocalDate(), + expiryDate = randomLocalDate(), + ) + ), + SEX to IsoSexEnum.NOT_APPLICABLE, + HEIGHT to Random.nextUInt(150u, 210u), + WEIGHT to Random.nextUInt(60u, 120u), + PORTRAIT_CAPTURE_DATE to randomLocalDate(), + AGE_IN_YEARS to Random.nextUInt(1u, 99u), + AGE_BIRTH_YEAR to Random.nextUInt(1900u, 2100u), + SIGNATURE_USUAL_MARK to Random.nextBytes(32) + ) + +private fun randomLocalDate() = LocalDate(Random.nextInt(1900, 2100), Random.nextInt(1, 12), Random.nextInt(1, 28)) From e632496af10ec1e14dbc0d633842c1a019cc3c35 Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Mon, 30 Sep 2024 12:12:22 +0200 Subject: [PATCH 12/13] Fix driving privileges to be an array (instead of a list) --- .../commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt | 2 +- .../kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt | 5 +---- .../at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt | 6 +++--- .../asitplus/wallet/mdl/MobileDrivingLicenceJwsNamespace.kt | 6 +++--- .../kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt | 2 +- .../commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt | 2 +- .../kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt | 2 +- .../at/asitplus/wallet/mdl/SerializerRegistrationTest.kt | 2 +- 8 files changed, 12 insertions(+), 15 deletions(-) diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt index 6c8b1b5..4366f8a 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/Initializer.kt @@ -26,7 +26,7 @@ object Initializer { LibraryInitializer.registerExtensionLibrary( credentialScheme = MobileDrivingLicenceScheme, jsonValueEncoder = jsonValueEncoder(), - itemValueDecoderMap = mapOf( + itemValueSerializerMap = mapOf( MobileDrivingLicenceDataElements.BIRTH_DATE to LocalDate.serializer(), MobileDrivingLicenceDataElements.ISSUE_DATE to LocalDate.serializer(), MobileDrivingLicenceDataElements.EXPIRY_DATE to LocalDate.serializer(), diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt index e14517a..ecb27f5 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicence.kt @@ -41,7 +41,6 @@ import kotlinx.datetime.LocalDate import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.cbor.ByteString -import kotlinx.serialization.cbor.ValueTags import kotlinx.serialization.decodeFromByteArray import kotlinx.serialization.encodeToByteArray @@ -70,8 +69,6 @@ data class MobileDrivingLicence( /** Date when mDL expires. */ @SerialName(EXPIRY_DATE) val expiryDate: LocalDate, - - /** Alpha-2 country code, as defined in ISO 3166-1, of the issuing authority's country or territory. */ @SerialName(ISSUING_COUNTRY) val issuingCountry: String? = null, @@ -91,7 +88,7 @@ data class MobileDrivingLicence( /** Driving privileges of the mDL holder. */ @SerialName(DRIVING_PRIVILEGES) - val drivingPrivileges: List, + val drivingPrivileges: Array, /** Distinguishing sign of the issuing country according to ISO/IEC 18013-1:2018, Annex F. */ @SerialName(UN_DISTINGUISHING_SIGN) diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt index 29b6fba..b52c87d 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJws.kt @@ -3,7 +3,7 @@ package at.asitplus.wallet.mdl import at.asitplus.KmmResult.Companion.wrap import at.asitplus.signum.indispensable.cosef.InstantLongSerializer import at.asitplus.wallet.lib.data.NullableInstantLongSerializer -import at.asitplus.wallet.lib.data.jsonSerializer +import at.asitplus.wallet.lib.data.vckJsonSerializer import kotlinx.datetime.Instant import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -27,11 +27,11 @@ data class MobileDrivingLicenceJws( val expiration: Instant?, ) { - fun serialize() = jsonSerializer.encodeToString(this) + fun serialize() = vckJsonSerializer.encodeToString(this) companion object { fun deserialize(it: String) = kotlin.runCatching { - jsonSerializer.decodeFromString(it) + vckJsonSerializer.decodeFromString(it) }.wrap() } diff --git a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJwsNamespace.kt b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJwsNamespace.kt index 0bf86f3..1996626 100644 --- a/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJwsNamespace.kt +++ b/mobiledrivinglicence/src/commonMain/kotlin/at/asitplus/wallet/mdl/MobileDrivingLicenceJwsNamespace.kt @@ -1,7 +1,7 @@ package at.asitplus.wallet.mdl import at.asitplus.KmmResult.Companion.wrap -import at.asitplus.wallet.lib.data.jsonSerializer +import at.asitplus.wallet.lib.data.vckJsonSerializer import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString @@ -15,11 +15,11 @@ data class MobileDrivingLicenceJwsNamespace( val mdl: MobileDrivingLicence, ) { - fun serialize() = jsonSerializer.encodeToString(this) + fun serialize() = vckJsonSerializer.encodeToString(this) companion object { fun deserialize(it: String) = kotlin.runCatching { - jsonSerializer.decodeFromString(it) + vckJsonSerializer.decodeFromString(it) }.wrap() } diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt index 96a4f39..3113974 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/CborSerializationTest.kt @@ -33,7 +33,7 @@ class CborSerializationTest : FreeSpec({ issuingAuthority = "LPD Steiermark", licenceNumber = "A/3f984/019", portrait = Random.nextBytes(16), - drivingPrivileges = listOf( + drivingPrivileges = arrayOf( DrivingPrivilege( vehicleCategoryCode = "A", issueDate = LocalDate.parse("2018-08-09"), diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt index d4f893c..e537da3 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/IsoMdocTest.kt @@ -85,7 +85,7 @@ class Wallet { portrait = byteArrayOf(), issueDate = LocalDate.parse(issueDateValue), expiryDate = LocalDate.parse(expiryDateValue), - drivingPrivileges = drivingPrivilegesValue.toList(), + drivingPrivileges = drivingPrivilegesValue, ) } diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt index 9c8d8f1..7a22e2c 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/JsonSerializationTest.kt @@ -71,7 +71,7 @@ class JsonSerializationTest : FreeSpec({ issuingAuthority = "LPD Steiermark", licenceNumber = "A/3f984/019", portrait = Random.nextBytes(16), - drivingPrivileges = listOf( + drivingPrivileges = arrayOf( DrivingPrivilege( vehicleCategoryCode = "A", issueDate = LocalDate.parse("2018-08-09"), diff --git a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt index afb8e9b..7884b19 100644 --- a/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt +++ b/mobiledrivinglicence/src/commonTest/kotlin/at/asitplus/wallet/mdl/SerializerRegistrationTest.kt @@ -53,7 +53,7 @@ private fun dataMap(): Map = ISSUE_DATE to randomLocalDate(), EXPIRY_DATE to randomLocalDate(), PORTRAIT to Random.nextBytes(32), - DRIVING_PRIVILEGES to listOf( + DRIVING_PRIVILEGES to arrayOf( DrivingPrivilege( vehicleCategoryCode = "A", issueDate = randomLocalDate(), From 49e0665374150165bcdc19b98420f9bdc2518d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Pr=C3=BCnster?= Date: Wed, 2 Oct 2024 14:57:01 +0200 Subject: [PATCH 13/13] release 1.1.0 (VC-K 5.0.0) --- gradle.properties | 2 +- mobiledrivinglicence/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 115ff1f..ec57d44 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,5 +12,5 @@ kotlin.mpp.enableCInteropCommonization=true kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -artifactVersion = 1.1.0-SNAPSHOT +artifactVersion = 1.1.0 jdk.version=17 diff --git a/mobiledrivinglicence/build.gradle.kts b/mobiledrivinglicence/build.gradle.kts index b19a067..8447978 100644 --- a/mobiledrivinglicence/build.gradle.kts +++ b/mobiledrivinglicence/build.gradle.kts @@ -25,7 +25,7 @@ kotlin { sourceSets { commonMain { dependencies { - api("at.asitplus.wallet:vck:5.0.0-SNAPSHOT") + api("at.asitplus.wallet:vck:5.0.0") } } }