Skip to content

Commit 2298cfc

Browse files
authored
fix: remove id from diddoc service encoding (#17)
1 parent 2fa0472 commit 2298cfc

File tree

3 files changed

+168
-117
lines changed

3 files changed

+168
-117
lines changed

didpeer/src/commonMain/kotlin/io/iohk/atala/prism/didcomm/didpeer/core/PeerDIDHelper.kt

Lines changed: 151 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import io.iohk.atala.prism.didcomm.didpeer.PeerDID
1010
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_ACCEPT
1111
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_DIDCOMM_MESSAGING
1212
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_ENDPOINT
13+
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_ID
1314
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_ROUTING_KEYS
1415
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_TYPE
1516
import io.iohk.atala.prism.didcomm.didpeer.SERVICE_URI
@@ -24,7 +25,10 @@ import io.iohk.atala.prism.didcomm.didpeer.VerificationMethodTypeAuthentication
2425
import io.iohk.atala.prism.didcomm.didpeer.VerificationMethodTypePeerDID
2526
import kotlinx.serialization.SerializationException
2627
import kotlinx.serialization.json.Json
28+
import kotlinx.serialization.json.JsonArray
2729
import kotlinx.serialization.json.JsonObject
30+
import kotlinx.serialization.json.buildJsonArray
31+
import kotlinx.serialization.json.buildJsonObject
2832
import kotlinx.serialization.json.jsonArray
2933
import kotlinx.serialization.json.jsonObject
3034
import kotlin.jvm.JvmName
@@ -36,24 +40,21 @@ import kotlin.jvm.JvmName
3640
* @property prefix The character value of the prefix
3741
*/
3842
internal enum class Numalgo2Prefix(val prefix: Char) {
39-
AUTHENTICATION('V'),
40-
KEY_AGREEMENT('E'),
41-
SERVICE('S')
43+
AUTHENTICATION('V'), KEY_AGREEMENT('E'), SERVICE('S')
4244
}
4345

4446
/**
4547
* Prefix values used for encoding and decoding services.
4648
* Each prefix corresponds to a specific service type.
4749
*/
48-
private val ServicePrefix =
49-
mapOf(
50-
SERVICE_TYPE to "t",
51-
SERVICE_ENDPOINT to "s",
52-
SERVICE_DIDCOMM_MESSAGING to "dm",
53-
SERVICE_ROUTING_KEYS to "r",
54-
SERVICE_ACCEPT to "a",
55-
SERVICE_URI to "uri"
56-
)
50+
private val ServicePrefix = mapOf(
51+
SERVICE_TYPE to "t",
52+
SERVICE_ENDPOINT to "s",
53+
SERVICE_DIDCOMM_MESSAGING to "dm",
54+
SERVICE_ROUTING_KEYS to "r",
55+
SERVICE_ACCEPT to "a",
56+
SERVICE_URI to "uri"
57+
)
5758

5859
/**
5960
* Encodes a service based on the provided JSON string.
@@ -87,9 +88,11 @@ internal fun encodeService(service: JSON): String {
8788
encodeIndividualService(trimmedService)
8889
}
8990
}
91+
9092
trimmedService.startsWith("{") -> {
9193
encodeIndividualService(trimmedService)
9294
}
95+
9396
else -> throw IllegalArgumentException("Invalid JSON format")
9497
}
9598
}
@@ -101,16 +104,45 @@ internal fun encodeService(service: JSON): String {
101104
* @return The encoded service string
102105
*/
103106
fun encodeIndividualService(service: JSON): String {
104-
val serviceToEncode = service.replace(Regex("[\n\t\\s]*"), "")
105-
.replace(SERVICE_TYPE, ServicePrefix.getValue(SERVICE_TYPE))
106-
.replace(SERVICE_ENDPOINT, ServicePrefix.getValue(SERVICE_ENDPOINT))
107-
.replace(SERVICE_DIDCOMM_MESSAGING, ServicePrefix.getValue(SERVICE_DIDCOMM_MESSAGING))
108-
.replace(SERVICE_ROUTING_KEYS, ServicePrefix.getValue(SERVICE_ROUTING_KEYS))
109-
.replace(SERVICE_ACCEPT, ServicePrefix.getValue(SERVICE_ACCEPT))
107+
val newService = removeIdFromService(service)
108+
val serviceToEncode =
109+
newService.replace(Regex("[\n\t\\s]*"), "").replace(SERVICE_TYPE, ServicePrefix.getValue(SERVICE_TYPE))
110+
.replace(SERVICE_ENDPOINT, ServicePrefix.getValue(SERVICE_ENDPOINT))
111+
.replace(SERVICE_DIDCOMM_MESSAGING, ServicePrefix.getValue(SERVICE_DIDCOMM_MESSAGING))
112+
.replace(SERVICE_ROUTING_KEYS, ServicePrefix.getValue(SERVICE_ROUTING_KEYS))
113+
.replace(SERVICE_ACCEPT, ServicePrefix.getValue(SERVICE_ACCEPT))
110114
val encodedService = serviceToEncode.encodeToByteArray().base64UrlEncoded
111115
return ".${Numalgo2Prefix.SERVICE.prefix}$encodedService"
112116
}
113117

118+
private fun removeIdFromService(service: JSON): String {
119+
val jsonElement = Json.parseToJsonElement(service)
120+
if (jsonElement is JsonArray) {
121+
val array = buildJsonArray {
122+
jsonElement.forEach { element ->
123+
add(buildJsonObject {
124+
element.jsonObject.forEach { (key, value) ->
125+
if (key != SERVICE_ID) {
126+
put(key, value)
127+
}
128+
129+
}
130+
})
131+
}
132+
}
133+
return array.toString()
134+
} else {
135+
val newElement = buildJsonObject {
136+
jsonElement.jsonObject.forEach { (key, value) ->
137+
if (key != SERVICE_ID) {
138+
put(key, value)
139+
}
140+
}
141+
}
142+
return newElement.toString()
143+
}
144+
}
145+
114146
/**
115147
* Decodes [encodedServices] according to PeerDID spec
116148
* @see
@@ -135,25 +167,23 @@ internal fun decodeService(encodedServices: List<JSON>, peerDID: PeerDID): List<
135167
decodedServices.joinToString(separator = ",", prefix = "[", postfix = "]")
136168
}
137169

138-
val serviceMapList =
170+
val serviceMapList = try {
171+
fromJsonToList(decodedServicesJson)
172+
} catch (e: SerializationException) {
139173
try {
140-
fromJsonToList(decodedServicesJson)
174+
listOf(fromJsonToMap(decodedServicesJson))
141175
} catch (e: SerializationException) {
142-
try {
143-
listOf(fromJsonToMap(decodedServicesJson))
144-
} catch (e: SerializationException) {
145-
throw IllegalArgumentException("Invalid JSON $decodedServices")
146-
}
176+
throw IllegalArgumentException("Invalid JSON $decodedServices")
147177
}
178+
}
148179

149180
return serviceMapList.mapIndexed { serviceNumber, serviceMap ->
150181
if (!serviceMap.containsKey(ServicePrefix.getValue(SERVICE_TYPE))) {
151182
throw IllegalArgumentException("service doesn't contain a type")
152183
}
153184

154-
val serviceType =
155-
serviceMap.getValue(ServicePrefix.getValue(SERVICE_TYPE)).toString()
156-
.replace(ServicePrefix.getValue(SERVICE_DIDCOMM_MESSAGING), SERVICE_DIDCOMM_MESSAGING)
185+
val serviceType = serviceMap.getValue(ServicePrefix.getValue(SERVICE_TYPE)).toString()
186+
.replace(ServicePrefix.getValue(SERVICE_DIDCOMM_MESSAGING), SERVICE_DIDCOMM_MESSAGING)
157187
val serviceId = if (serviceMapList.size > 1) {
158188
if (serviceNumber == 0) {
159189
"#service"
@@ -167,26 +197,49 @@ internal fun decodeService(encodedServices: List<JSON>, peerDID: PeerDID): List<
167197
val serviceEndpointMap = mutableMapOf<String, Any>()
168198
when (val serviceEndpointValue = serviceMap[ServicePrefix.getValue(SERVICE_ENDPOINT)]) {
169199
is String -> {
170-
serviceMap[ServicePrefix.getValue(SERVICE_ENDPOINT)]?.let { serviceEndpointMap.put(SERVICE_URI, it) }
171-
serviceMap[ServicePrefix.getValue(SERVICE_ROUTING_KEYS)]?.let { serviceEndpointMap.put(SERVICE_ROUTING_KEYS, it) }
172-
serviceMap[ServicePrefix.getValue(SERVICE_ACCEPT)]?.let { serviceEndpointMap.put(SERVICE_ACCEPT, it) }
200+
serviceMap[ServicePrefix.getValue(SERVICE_ENDPOINT)]?.let {
201+
serviceEndpointMap.put(
202+
SERVICE_URI, it
203+
)
204+
}
205+
serviceMap[ServicePrefix.getValue(SERVICE_ROUTING_KEYS)]?.let {
206+
serviceEndpointMap.put(
207+
SERVICE_ROUTING_KEYS, it
208+
)
209+
}
210+
serviceMap[ServicePrefix.getValue(SERVICE_ACCEPT)]?.let {
211+
serviceEndpointMap.put(
212+
SERVICE_ACCEPT, it
213+
)
214+
}
173215
}
216+
174217
is Map<*, *> -> {
175-
serviceEndpointValue[ServicePrefix.getValue(SERVICE_URI)]?.let { serviceEndpointMap.put(SERVICE_URI, it) }
176-
serviceEndpointValue[ServicePrefix.getValue(SERVICE_ROUTING_KEYS)]?.let { serviceEndpointMap.put(SERVICE_ROUTING_KEYS, it) }
177-
serviceEndpointValue[ServicePrefix.getValue(SERVICE_ACCEPT)]?.let { serviceEndpointMap.put(SERVICE_ACCEPT, it) }
218+
serviceEndpointValue[ServicePrefix.getValue(SERVICE_URI)]?.let {
219+
serviceEndpointMap.put(
220+
SERVICE_URI, it
221+
)
222+
}
223+
serviceEndpointValue[ServicePrefix.getValue(SERVICE_ROUTING_KEYS)]?.let {
224+
serviceEndpointMap.put(
225+
SERVICE_ROUTING_KEYS, it
226+
)
227+
}
228+
serviceEndpointValue[ServicePrefix.getValue(SERVICE_ACCEPT)]?.let {
229+
serviceEndpointMap.put(
230+
SERVICE_ACCEPT, it
231+
)
232+
}
178233
}
234+
179235
else -> {
180236
throw IllegalArgumentException("Service doesn't contain a valid Endpoint")
181237
}
182238
}
183239

184-
val service =
185-
mutableMapOf<String, Any>(
186-
"id" to serviceId,
187-
"type" to serviceType,
188-
"serviceEndpoint" to serviceEndpointMap
189-
)
240+
val service = mutableMapOf<String, Any>(
241+
"id" to serviceId, "type" to serviceType, "serviceEndpoint" to serviceEndpointMap
242+
)
190243

191244
OtherService(service)
192245
}.toList()
@@ -201,12 +254,11 @@ internal fun decodeService(encodedServices: List<JSON>, peerDID: PeerDID): List<
201254
* @return transform+encnumbasis
202255
*/
203256
internal fun createMultibaseEncnumbasis(key: VerificationMaterialPeerDID<out VerificationMethodTypePeerDID>): String {
204-
val decodedKey =
205-
when (key.format) {
206-
VerificationMaterialFormatPeerDID.BASE58 -> fromBase58(key.value.toString())
207-
VerificationMaterialFormatPeerDID.MULTIBASE -> fromMulticodec(fromBase58Multibase(key.value.toString()).second).second
208-
VerificationMaterialFormatPeerDID.JWK -> fromJwk(key)
209-
}
257+
val decodedKey = when (key.format) {
258+
VerificationMaterialFormatPeerDID.BASE58 -> fromBase58(key.value.toString())
259+
VerificationMaterialFormatPeerDID.MULTIBASE -> fromMulticodec(fromBase58Multibase(key.value.toString()).second).second
260+
VerificationMaterialFormatPeerDID.JWK -> fromJwk(key)
261+
}
210262
validateRawKeyLength(decodedKey)
211263
return toBase58Multibase(toMulticodec(decodedKey, key.type))
212264
}
@@ -218,8 +270,7 @@ internal fun createMultibaseEncnumbasis(key: VerificationMaterialPeerDID<out Ver
218270
* @property verMaterial The verification material.
219271
*/
220272
internal data class DecodedEncumbasis(
221-
val encnumbasis: String,
222-
val verMaterial: VerificationMaterialPeerDID<out VerificationMethodTypePeerDID>
273+
val encnumbasis: String, val verMaterial: VerificationMaterialPeerDID<out VerificationMethodTypePeerDID>
223274
)
224275

225276
/**
@@ -230,78 +281,64 @@ internal data class DecodedEncumbasis(
230281
* @return decoded encnumbasis as verification material for DID DOC
231282
*/
232283
internal fun decodeMultibaseEncnumbasis(
233-
multibase: String,
234-
format: VerificationMaterialFormatPeerDID
284+
multibase: String, format: VerificationMaterialFormatPeerDID
235285
): DecodedEncumbasis {
236286
val (encnumbasis, decodedEncnumbasis) = fromBase58Multibase(multibase)
237287
val (codec, decodedEncnumbasisWithoutPrefix) = fromMulticodec(decodedEncnumbasis)
238288
validateRawKeyLength(decodedEncnumbasisWithoutPrefix)
239289

240-
val verMaterial =
241-
when (format) {
242-
VerificationMaterialFormatPeerDID.BASE58 ->
243-
when (codec) {
244-
Codec.X25519 ->
245-
VerificationMaterialAgreement(
246-
format = format,
247-
type = VerificationMethodTypeAgreement.X25519KeyAgreementKey2019,
248-
value = toBase58(decodedEncnumbasisWithoutPrefix)
249-
)
250-
Codec.ED25519 ->
251-
VerificationMaterialAuthentication(
252-
format = format,
253-
type = VerificationMethodTypeAuthentication.ED25519VerificationKey2018,
254-
value = toBase58(decodedEncnumbasisWithoutPrefix)
255-
)
256-
}
257-
VerificationMaterialFormatPeerDID.MULTIBASE ->
258-
when (codec) {
259-
Codec.X25519 ->
260-
VerificationMaterialAgreement(
261-
format = format,
262-
type = VerificationMethodTypeAgreement.X25519KeyAgreementKey2020,
263-
value =
264-
toBase58Multibase(
265-
toMulticodec(
266-
decodedEncnumbasisWithoutPrefix,
267-
VerificationMethodTypeAgreement.X25519KeyAgreementKey2020
268-
)
269-
)
270-
)
271-
Codec.ED25519 ->
272-
VerificationMaterialAuthentication(
273-
format = format,
274-
type = VerificationMethodTypeAuthentication.ED25519VerificationKey2020,
275-
value =
276-
toBase58Multibase(
277-
toMulticodec(
278-
decodedEncnumbasisWithoutPrefix,
279-
VerificationMethodTypeAuthentication.ED25519VerificationKey2020
280-
)
281-
)
282-
)
283-
}
284-
VerificationMaterialFormatPeerDID.JWK ->
285-
when (codec) {
286-
Codec.X25519 ->
287-
VerificationMaterialAgreement(
288-
format = format,
289-
type = VerificationMethodTypeAgreement.JsonWebKey2020,
290-
value = toJwk(decodedEncnumbasisWithoutPrefix, VerificationMethodTypeAgreement.JsonWebKey2020)
291-
)
292-
Codec.ED25519 ->
293-
VerificationMaterialAuthentication(
294-
format = format,
295-
type = VerificationMethodTypeAuthentication.JsonWebKey2020,
296-
value =
297-
toJwk(
298-
decodedEncnumbasisWithoutPrefix,
299-
VerificationMethodTypeAuthentication.JsonWebKey2020
300-
)
301-
)
302-
}
290+
val verMaterial = when (format) {
291+
VerificationMaterialFormatPeerDID.BASE58 -> when (codec) {
292+
Codec.X25519 -> VerificationMaterialAgreement(
293+
format = format,
294+
type = VerificationMethodTypeAgreement.X25519KeyAgreementKey2019,
295+
value = toBase58(decodedEncnumbasisWithoutPrefix)
296+
)
297+
298+
Codec.ED25519 -> VerificationMaterialAuthentication(
299+
format = format,
300+
type = VerificationMethodTypeAuthentication.ED25519VerificationKey2018,
301+
value = toBase58(decodedEncnumbasisWithoutPrefix)
302+
)
303303
}
304304

305+
VerificationMaterialFormatPeerDID.MULTIBASE -> when (codec) {
306+
Codec.X25519 -> VerificationMaterialAgreement(
307+
format = format,
308+
type = VerificationMethodTypeAgreement.X25519KeyAgreementKey2020,
309+
value = toBase58Multibase(
310+
toMulticodec(
311+
decodedEncnumbasisWithoutPrefix, VerificationMethodTypeAgreement.X25519KeyAgreementKey2020
312+
)
313+
)
314+
)
315+
316+
Codec.ED25519 -> VerificationMaterialAuthentication(
317+
format = format,
318+
type = VerificationMethodTypeAuthentication.ED25519VerificationKey2020,
319+
value = toBase58Multibase(
320+
toMulticodec(
321+
decodedEncnumbasisWithoutPrefix, VerificationMethodTypeAuthentication.ED25519VerificationKey2020
322+
)
323+
)
324+
)
325+
}
326+
327+
VerificationMaterialFormatPeerDID.JWK -> when (codec) {
328+
Codec.X25519 -> VerificationMaterialAgreement(
329+
format = format, type = VerificationMethodTypeAgreement.JsonWebKey2020, value = toJwk(
330+
decodedEncnumbasisWithoutPrefix, VerificationMethodTypeAgreement.JsonWebKey2020
331+
)
332+
)
333+
334+
Codec.ED25519 -> VerificationMaterialAuthentication(
335+
format = format, type = VerificationMethodTypeAuthentication.JsonWebKey2020, value = toJwk(
336+
decodedEncnumbasisWithoutPrefix, VerificationMethodTypeAuthentication.JsonWebKey2020
337+
)
338+
)
339+
}
340+
}
341+
305342
return DecodedEncumbasis(encnumbasis, verMaterial)
306343
}
307344

@@ -315,7 +352,5 @@ internal fun decodeMultibaseEncnumbasis(
315352
*/
316353
internal fun getVerificationMethod(keyId: Int, did: String, decodedEncumbasis: DecodedEncumbasis) =
317354
VerificationMethodPeerDID(
318-
id = "$did#key-$keyId",
319-
controller = did,
320-
verMaterial = decodedEncumbasis.verMaterial
355+
id = "$did#key-$keyId", controller = did, verMaterial = decodedEncumbasis.verMaterial
321356
)

0 commit comments

Comments
 (0)