Skip to content

Commit

Permalink
Add more documentation to custom ISO data classes
Browse files Browse the repository at this point in the history
  • Loading branch information
nodh committed Jul 24, 2023
1 parent 37405c6 commit 06365d1
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import kotlinx.serialization.encoding.Encoder
*/
@OptIn(ExperimentalSerializationApi::class)
@Serializable
@CborArray(18U)
@CborArray
data class CoseSigned(
@Serializable(with = ByteStringWrapperCoseHeaderSerializer::class)
@ByteString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,30 @@ data class ItemsRequest(
)



/**
* Convenience class with a custom serializer ([ItemsRequestListSerializer]) to prevent
* usage of the type `Map<String, Map<String, Boolean>>` in [ItemsRequest.namespaces].
*/
@Serializable(with = ItemsRequestListSerializer::class)
data class ItemsRequestList(
val entries: List<SingleItemsRequest>
)

/**
* Convenience class with a custom serializer ([ItemsRequestListSerializer]) to prevent
* usage of the type `Map<String, Map<String, Boolean>>` in [ItemsRequest.namespaces].
*/
data class SingleItemsRequest(
val key: String,
val value: Boolean,
)

/**
* Serializes [ItemsRequestList.entries] as an "inline map",
* having [SingleItemsRequest.key] as the map key and [SingleItemsRequest.value] as the map value,
* for the map represented by [ItemsRequestList].
*/
object ItemsRequestListSerializer : KSerializer<ItemsRequestList> {

override val descriptor: SerialDescriptor = mapSerialDescriptor(
Expand Down Expand Up @@ -244,6 +258,10 @@ data class IssuerSigned(
}


/**
* Convenience class with a custom serializer ([IssuerSignedListSerializer]) to prevent
* usage of the type `Map<String, List<ByteStringWrapper<IssuerSignedItem>>>` in [IssuerSigned.namespaces].
*/
@Serializable(with = IssuerSignedListSerializer::class)
data class IssuerSignedList(
val entries: List<ByteStringWrapper<IssuerSignedItem>>
Expand All @@ -260,6 +278,10 @@ data class IssuerSignedList(
}
}

/**
* Serializes [IssuerSignedList.entries] as an "inline list",
* having serialized instances of [IssuerSignedItem] as the values.
*/
object IssuerSignedListSerializer : KSerializer<IssuerSignedList> {

override val descriptor: SerialDescriptor = listSerialDescriptor(
Expand Down Expand Up @@ -350,6 +372,9 @@ data class IssuerSignedItem(
}
}

/**
* Convenience class to enable serialization of (nearly) "any" value in [IssuerSignedItem.elementValue]
*/
// TODO Could this be anything else?
@Serializable(with = ElementValueSerializer::class)
data class ElementValue(
Expand Down Expand Up @@ -437,6 +462,7 @@ data class DeviceSigned(
}
}

// TODO see if we really need this class
data class DeviceNameSpaces(
@SerialName(NAMESPACE_MDL)
val entries: Map<String, ElementValue>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,19 @@ data class MobileSecurityObject(
}
}

/**
* Convenience class with a custom serializer ([ValueDigestListSerializer]) to prevent
* usage of the type `Map<String, Map<UInt, ByteArray>>` in [MobileSecurityObject.valueDigests].
*/
@Serializable(with = ValueDigestListSerializer::class)
data class ValueDigestList(
val entries: List<ValueDigest>
)

/**
* Convenience class with a custom serializer ([ValueDigestListSerializer]) to prevent
* usage of the type `Map<String, Map<UInt, ByteArray>>` in [MobileSecurityObject.valueDigests].
*/
data class ValueDigest(
val key: UInt,
val value: ByteArray,
Expand Down Expand Up @@ -105,10 +113,13 @@ data class ValueDigest(
value.serialize().wrapInCborTag(24).sha256()
)
}

}


/**
* Serialized the [ValueDigestList.entries] as an "inline map",
* meaning [ValueDigest.key] is the map key and [ValueDigest.value] the map value,
* for the map represented by [ValueDigestList]
*/
object ValueDigestListSerializer : KSerializer<ValueDigestList> {

override val descriptor: SerialDescriptor = mapSerialDescriptor(
Expand All @@ -121,6 +132,7 @@ object ValueDigestListSerializer : KSerializer<ValueDigestList> {
var index = 0
value.entries.forEach {
this.encodeIntElement(descriptor, index++, it.key.toInt())
// TODO Values need to be tagged with 24 ... resulting in prefix D818
this.encodeSerializableElement(descriptor, index++, ByteArraySerializer(), it.value)
}
}
Expand All @@ -147,7 +159,6 @@ object ValueDigestListSerializer : KSerializer<ValueDigestList> {
}
}


/**
* Part of the ISO/IEC 18013-5:2021 standard: Data structure for MSO (9.1.2.4)
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.asitplus.wallet.lib.iso

import at.asitplus.wallet.lib.data.jsonSerializer
import at.asitplus.wallet.lib.jws.JwsSigned
import io.github.aakira.napier.Napier
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -75,8 +76,8 @@ data class ServerResponse(
@SerialName("documentErrors")
val documentErrors: Map<String, Int>? = null,
) {

fun serialize() = jsonSerializer.encodeToString(this)

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.ktor.util.Identity.encode
import io.ktor.utils.io.core.toByteArray
import io.matthewnelson.component.encoding.base16.decodeBase16ToArray
import io.matthewnelson.component.encoding.base16.encodeBase16
Expand Down Expand Up @@ -157,6 +158,9 @@ class CborSerializationTest : FreeSpec({

docRequest.readerAuth.shouldNotBeNull()
docRequest.readerAuth?.unprotectedHeader?.certificateChain?.shouldNotBeNull()

// TODO Needs definite length for arrays, e.g. in deviceRequest.docRequests
//deviceRequest.serialize().encodeBase16().uppercase() shouldBe input
}

// From ISO/IEC 18013-5:2021(E), D4.1.2, page 116
Expand Down Expand Up @@ -377,6 +381,9 @@ class CborSerializationTest : FreeSpec({
.decodeBase16ToArray()
valueDigestListUs.findItem(1U) shouldBe "4D80E1E2E4FB246D97895427CE7000BB59BB24C8CD003ECF94BF35BBD2917E34"
.decodeBase16ToArray()

// TODO D818 is the tags for digests
//deviceResponse.serialize().encodeBase16() shouldBe input
}

"Driving Privilege" {
Expand Down Expand Up @@ -546,6 +553,9 @@ class CborSerializationTest : FreeSpec({
.decodeBase16ToArray()
valueDigestListUs.findItem(1U) shouldBe "4D80E1E2E4FB246D97895427CE7000BB59BB24C8CD003ECF94BF35BBD2917E34"
.decodeBase16ToArray()

// TODO only A7 vs A1 for serialized CoseHeader is wrong!
//coseSigned.serialize().encodeBase16() shouldBe input
}

})
Expand Down

0 comments on commit 06365d1

Please sign in to comment.