diff --git a/build.gradle.kts b/build.gradle.kts index 09d66669..023250d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,7 +38,7 @@ dependencies { implementation("com.microsoft.azure:azure-client-authentication:1.7.14") implementation("com.nimbusds:nimbus-jose-jwt:9.30.2") implementation("com.nimbusds:oauth2-oidc-sdk:10.7") - implementation("id.walt:waltid-sd-jwt-jvm:1.2306160840.0") + implementation("id.walt:waltid-sd-jwt-jvm:1.2306191408.0") implementation("org.bouncycastle:bcprov-jdk15to18:1.72") implementation("org.bouncycastle:bcpkix-jdk15to18:1.72") diff --git a/src/main/kotlin/id/walt/cli/did/DidCommand.kt b/src/main/kotlin/id/walt/cli/did/DidCommand.kt index 1aea0bd3..5e6b300e 100644 --- a/src/main/kotlin/id/walt/cli/did/DidCommand.kt +++ b/src/main/kotlin/id/walt/cli/did/DidCommand.kt @@ -68,7 +68,7 @@ class CreateDidCommand : CliktCommand( is WebMethodOption -> DidService.create(web, keyId, DidWebCreateOptions((method as WebMethodOption).domain, (method as WebMethodOption).path)) is EbsiMethodOption -> DidService.create(ebsi, keyId, DidEbsiCreateOptions((method as EbsiMethodOption).version)) is CheqdMethodOption -> DidService.create(cheqd, keyId, DidCheqdCreateOptions((method as CheqdMethodOption).network)) - is KeyMethodOption -> DidService.create(key, keyId, DidKeyCreateOptions((method as KeyMethodOption).isJwk)) + is KeyMethodOption -> DidService.create(key, keyId, DidKeyCreateOptions((method as KeyMethodOption).useJwkJcsPubMulticodec)) else -> DidService.create(DidMethod.valueOf(method.method), keyId) } diff --git a/src/main/kotlin/id/walt/cli/did/DidMethodOptions.kt b/src/main/kotlin/id/walt/cli/did/DidMethodOptions.kt index 3653566f..dedbe152 100644 --- a/src/main/kotlin/id/walt/cli/did/DidMethodOptions.kt +++ b/src/main/kotlin/id/walt/cli/did/DidMethodOptions.kt @@ -23,5 +23,5 @@ class CheqdMethodOption : DidMethodOption("cheqd") { val network: String by option("-n", "--network", help = "did:cheqd - Specify the network [testnet]").choice("mainnet", "testnet").default("testnet") } class KeyMethodOption : DidMethodOption("key") { - val isJwk: Boolean by option("-j", "--is-jwk", help = "did:key - is jwk_jcs-pub").flag(default = false) + val useJwkJcsPubMulticodec: Boolean by option("-j", "--useJwkJcsPub", help = "did:key - use jwk_jcs-pub multicodec (0xeb51)").flag(default = false) } diff --git a/src/main/kotlin/id/walt/rest/core/DidController.kt b/src/main/kotlin/id/walt/rest/core/DidController.kt index 98c6b588..9da55d45 100644 --- a/src/main/kotlin/id/walt/rest/core/DidController.kt +++ b/src/main/kotlin/id/walt/rest/core/DidController.kt @@ -79,7 +79,7 @@ object DidController { is WebCreateDidRequest -> DidWebCreateOptions(request.domain ?: "walt.id", request.path) is EbsiCreateDidRequest -> DidEbsiCreateOptions(request.version) is CheqdCreateDidRequest -> DidCheqdCreateOptions(request.network) - is KeyCreateDidRequest -> DidKeyCreateOptions(request.isJwk) + is KeyCreateDidRequest -> DidKeyCreateOptions(request.useJwkJcsPub) else -> null } diff --git a/src/main/kotlin/id/walt/rest/core/requests/did/CreateDidRequest.kt b/src/main/kotlin/id/walt/rest/core/requests/did/CreateDidRequest.kt index 62c6e2f0..0f5e4a16 100644 --- a/src/main/kotlin/id/walt/rest/core/requests/did/CreateDidRequest.kt +++ b/src/main/kotlin/id/walt/rest/core/requests/did/CreateDidRequest.kt @@ -29,7 +29,7 @@ class CreateDidRequestMethodAdapter : TypeAdapter { @Serializable class KeyCreateDidRequest( override val keyAlias: String? = null, - val isJwk: Boolean = false, + val useJwkJcsPub: Boolean = false, ) : CreateDidRequest("key") @Serializable class WebCreateDidRequest( diff --git a/src/main/kotlin/id/walt/services/did/DidOptions.kt b/src/main/kotlin/id/walt/services/did/DidOptions.kt index 2fbfaee0..d0dd40da 100644 --- a/src/main/kotlin/id/walt/services/did/DidOptions.kt +++ b/src/main/kotlin/id/walt/services/did/DidOptions.kt @@ -5,6 +5,6 @@ sealed class DidOptions data class DidWebCreateOptions(val domain: String?, val path: String? = null) : DidOptions() data class DidEbsiCreateOptions(val version: Int) : DidOptions() data class DidCheqdCreateOptions(val network: String) : DidOptions() -data class DidKeyCreateOptions(val isJwk: Boolean) : DidOptions() +data class DidKeyCreateOptions(val useJwkJcsPub: Boolean) : DidOptions() data class DidEbsiResolveOptions(val isRaw: Boolean) : DidOptions() diff --git a/src/main/kotlin/id/walt/services/did/composers/DidKeyDocumentComposer.kt b/src/main/kotlin/id/walt/services/did/composers/DidKeyDocumentComposer.kt index 9998189b..3f69f894 100644 --- a/src/main/kotlin/id/walt/services/did/composers/DidKeyDocumentComposer.kt +++ b/src/main/kotlin/id/walt/services/did/composers/DidKeyDocumentComposer.kt @@ -39,25 +39,27 @@ class DidKeyDocumentComposer( * @param [pubKey] - the public key byte array * @return the [Did] document */ - private fun constructDidKey(didUrl: DidUrl, pubKey: ByteArray): DidKey = DidKey( - context = listOf( - "https://www.w3.org/ns/did/v1", - "https://w3id.org/security/suites/jws-2020/v1" - ), - id = didUrl.did, - verificationMethod = listOf( - VerificationMethod( - id = "${didUrl.did}#${didUrl.did}", - type = "JsonWebKey2020", - controller = didUrl.did, - publicKeyJwk = Klaxon().parse(JWK.parse(String(pubKey)).toJSONString()) - ) - ), - assertionMethod = listOf(VerificationMethod.Reference(didUrl.did)), - authentication = listOf(VerificationMethod.Reference(didUrl.did)), - capabilityInvocation = listOf(VerificationMethod.Reference(didUrl.did)), - capabilityDelegation = listOf(VerificationMethod.Reference(didUrl.did)), - ) + private fun constructDidKey(didUrl: DidUrl, pubKey: ByteArray): DidKey = "${didUrl.did}#${didUrl.identifier}".let { + DidKey( + context = listOf( + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ), + id = didUrl.did, + verificationMethod = listOf( + VerificationMethod( + id = it, + type = "JsonWebKey2020", + controller = didUrl.did, + publicKeyJwk = Klaxon().parse(JWK.parse(String(pubKey)).toJSONString()) + ) + ), + assertionMethod = listOf(VerificationMethod.Reference(it)), + authentication = listOf(VerificationMethod.Reference(it)), + capabilityInvocation = listOf(VerificationMethod.Reference(it)), + capabilityDelegation = listOf(VerificationMethod.Reference(it)), + ) + } /** * other types of did:key diff --git a/src/main/kotlin/id/walt/services/did/factories/DidKeyFactory.kt b/src/main/kotlin/id/walt/services/did/factories/DidKeyFactory.kt index 107040d5..f85fcd64 100644 --- a/src/main/kotlin/id/walt/services/did/factories/DidKeyFactory.kt +++ b/src/main/kotlin/id/walt/services/did/factories/DidKeyFactory.kt @@ -30,7 +30,7 @@ class DidKeyFactory( } private fun getIdentifierComponents(key: Key, options: DidKeyCreateOptions?): IdentifierComponents = - options?.takeIf { it.isJwk }?.let { + options?.takeIf { it.useJwkJcsPub }?.let { IdentifierComponents(JwkJcsPubMultiCodecKeyCode, getJwkPubKeyRequiredMembersBytes(key)) } ?: IdentifierComponents(getMulticodecKeyCode(key.algorithm), getPublicKeyBytesForDidKey(key)) diff --git a/src/main/kotlin/id/walt/signatory/rest/SignatoryController.kt b/src/main/kotlin/id/walt/signatory/rest/SignatoryController.kt index 9b08d2a9..7ace6901 100644 --- a/src/main/kotlin/id/walt/signatory/rest/SignatoryController.kt +++ b/src/main/kotlin/id/walt/signatory/rest/SignatoryController.kt @@ -7,6 +7,7 @@ import id.walt.credentials.w3c.VerifiableCredential import id.walt.credentials.w3c.builder.W3CCredentialBuilder import id.walt.credentials.w3c.toVerifiableCredential import id.walt.sdjwt.SDMap +import id.walt.sdjwt.SDMapBuilder import id.walt.signatory.ProofConfig import id.walt.signatory.ProofType import id.walt.signatory.Signatory @@ -110,9 +111,9 @@ object SignatoryController { fun issueCredentialDocs() = document().operation { it.summary("Issue a credential").operationId("issue").addTagsItem("Credentials").description( - "Based on a template (maintained in the VcLib), this call creates a W3C Verifiable Credential. Note that the 'templateId, issuerDid, and the subjectDid, are mandatory parameters. All other parameters are optional.

This is a example request, that also demonstrates how to populate the credential with custom data: the

{
" + " \"templateId\": \"VerifiableId\",
" + " \"config\": {
" + "      \"issuerDid\": \"did:ebsi:zuathxHtXTV8psijTjtuZD7\",
" + "      \"subjectDid\": \"did:key:z6MkwfgBDSMRqXaJtw5DjhkJdDsDmRNSrvrM1L6UMBDtvaSX\",
" + "      \"selectiveDisclosure\": {\n" + - " \"credentialSubject\": { \"sd\": true, \"nestedMap\": { \"firstName\": { \"sd\": true }}}\n" + - "}
},
" + " \"credentialData\": {
" + "      \"credentialSubject\": {
" + "          \"firstName\": \"Severin\"
" + "          }
" + "      }
" + "}
" + "Based on a template (maintained in the VcLib), this call creates a W3C Verifiable Credential. Note that the 'templateId, issuerDid, and the subjectDid, are mandatory parameters. All other parameters are optional.

This is a example request, that also demonstrates how to populate the credential with custom data: the

{
" + " \"templateId\": \"VerifiableId\",
" + " \"config\": {
" + "      \"issuerDid\": \"did:ebsi:zuathxHtXTV8psijTjtuZD7\",
" + "      \"subjectDid\": \"did:key:z6MkwfgBDSMRqXaJtw5DjhkJdDsDmRNSrvrM1L6UMBDtvaSX\",
" + "      \"selectiveDisclosure\": \n" + + SDMapBuilder().addField("credentialSubject", false, SDMapBuilder().addField("firstName", true).build()).build().toJSON().toString() + "\n" + + "
},
" + " \"credentialData\": {
" + "      \"credentialSubject\": {
" + "          \"firstName\": \"Severin\"
" + "          }
" + "      }
" + "}
" ) }.body() { it.description("IssueCredentialRequest: templateId: String, config: ProofConfig, credentialData: JsonObject") }.json("200") diff --git a/src/test/kotlin/id/walt/services/did/DidKeyCreationTest.kt b/src/test/kotlin/id/walt/services/did/DidKeyCreationTest.kt index ed441eb2..7387a9ce 100644 --- a/src/test/kotlin/id/walt/services/did/DidKeyCreationTest.kt +++ b/src/test/kotlin/id/walt/services/did/DidKeyCreationTest.kt @@ -54,7 +54,7 @@ class DidKeyCreationTest : StringSpec({ "Create jwk_jcs-pub did:key" { val jwkPubKey = "{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"ngy44T1vxAT6Di4nr-UaM9K3Tlnz9pkoksDokKFkmNc\",\"y\":\"QCRfOKlSM31GTkb4JHx3nXB4G_jSPMsbdjzlkT_UpPc\"}" val keyId = keyService.importKey(jwkPubKey) - val result = createAndLoadDid(keyId, DidKeyCreateOptions(isJwk = true)) + val result = createAndLoadDid(keyId, DidKeyCreateOptions(useJwkJcsPub = true)) result.id shouldBe "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" } }) diff --git a/src/test/kotlin/id/walt/services/did/DidServiceTest.kt b/src/test/kotlin/id/walt/services/did/DidServiceTest.kt index 19419dba..0da1057f 100644 --- a/src/test/kotlin/id/walt/services/did/DidServiceTest.kt +++ b/src/test/kotlin/id/walt/services/did/DidServiceTest.kt @@ -242,7 +242,7 @@ class DidServiceTest : AnnotationSpec() { val expectedResult = Did.decode(readWhenContent(File("src/test/resources/dids/did-key-jwk_jcs-pub.json")))!! val jwkPubKey = "{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"ngy44T1vxAT6Di4nr-UaM9K3Tlnz9pkoksDokKFkmNc\",\"y\":\"QCRfOKlSM31GTkb4JHx3nXB4G_jSPMsbdjzlkT_UpPc\"}" val keyId = keyService.importKey(jwkPubKey) - val did = DidService.create(DidMethod.key, keyId.id, DidKeyCreateOptions(isJwk = true)) + val did = DidService.create(DidMethod.key, keyId.id, DidKeyCreateOptions(useJwkJcsPub = true)) // when val result = DidService.resolve(did) // then diff --git a/src/test/kotlin/id/walt/signatory/SignatoryApiTest.kt b/src/test/kotlin/id/walt/signatory/SignatoryApiTest.kt index b867c280..7883240f 100644 --- a/src/test/kotlin/id/walt/signatory/SignatoryApiTest.kt +++ b/src/test/kotlin/id/walt/signatory/SignatoryApiTest.kt @@ -342,33 +342,6 @@ class SignatoryApiTest : AnnotationSpec() { }) } ) - val request = "{\n" + - " \"templateId\": \"VerifiableId\",\n" + - " \"config\": {\n" + - " \"issuerDid\": \"$did\",\n" + - " \"subjectDid\": \"$did\",\n" + - " \"proofType\": \"SD_JWT\",\n" + - " \"selectiveDisclosure\": {\n" + - " \"fields\": {\n" + - " \"credentialSubject\": {\n" + - " \"sd\": true,\n" + - " \"children\": {\n" + - " \"fields\": {\n" + - " \"firstName\": {\n" + - " \"sd\": true\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " },\n" + - " \"credentialData\": {\n" + - " \"credentialSubject\": {\n" + - " \"firstName\": \"Severin\"\n" + - " }\n" + - " }\n" + - "}" val vc = httpPost("/v1/credentials/issue", KlaxonWithConverters().toJsonString(reqObj)) println(vc) val parsedVc = vc?.toVerifiableCredential() diff --git a/src/test/resources/dids/did-key-jwk_jcs-pub.json b/src/test/resources/dids/did-key-jwk_jcs-pub.json index ba89f279..1d9ae997 100644 --- a/src/test/resources/dids/did-key-jwk_jcs-pub.json +++ b/src/test/resources/dids/did-key-jwk_jcs-pub.json @@ -1,32 +1,32 @@ { - "assertionMethod" : [ - "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" - ], - "authentication" : [ - "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" - ], - "capabilityDelegation" : [ - "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" - ], - "capabilityInvocation" : [ - "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" - ], - "@context" : [ + "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1" ], - "id" : "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r", - "verificationMethod" : [ + "id": "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r", + "verificationMethod": [ { - "controller" : "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r", - "id" : "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r#did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r", - "publicKeyJwk" : { - "crv" : "P-256", - "kty" : "EC", - "x" : "ngy44T1vxAT6Di4nr-UaM9K3Tlnz9pkoksDokKFkmNc", - "y" : "QCRfOKlSM31GTkb4JHx3nXB4G_jSPMsbdjzlkT_UpPc" - }, - "type" : "JsonWebKey2020" + "id": "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r#z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r", + "type": "JsonWebKey2020", + "controller": "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r", + "publicKeyJwk": { + "crv": "P-256", + "kty": "EC", + "x": "ngy44T1vxAT6Di4nr-UaM9K3Tlnz9pkoksDokKFkmNc", + "y": "QCRfOKlSM31GTkb4JHx3nXB4G_jSPMsbdjzlkT_UpPc" + } } + ], + "authentication": [ + "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r#z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" + ], + "assertionMethod": [ + "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r#z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" + ], + "capabilityInvocation": [ + "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r#z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" + ], + "capabilityDelegation": [ + "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r#z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r" ] }