diff --git a/build.gradle.kts b/build.gradle.kts index 17f2ac362..aa165b64f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { api("decentralized-identity:jsonld-common-java:1.1.0") implementation("com.goterl:lazysodium-java:5.1.4") implementation("net.java.dev.jna:jna:5.12.1") - implementation("com.github.multiformats:java-multibase:v1.1.0") + implementation("com.github.multiformats:java-multibase:v1.1.1") implementation("com.microsoft.azure:azure-keyvault:1.2.6") implementation("com.microsoft.azure:azure-client-authentication:1.7.14") implementation("com.nimbusds:nimbus-jose-jwt:9.30.2") diff --git a/src/main/kotlin/id/walt/services/did/DidService.kt b/src/main/kotlin/id/walt/services/did/DidService.kt index 48a253401..8b224f011 100644 --- a/src/main/kotlin/id/walt/services/did/DidService.kt +++ b/src/main/kotlin/id/walt/services/did/DidService.kt @@ -14,7 +14,7 @@ import id.walt.services.CryptoProvider import id.walt.services.WaltIdServices import id.walt.services.context.ContextManager import id.walt.services.crypto.CryptoService -import id.walt.services.did.resolvers.* +import id.walt.services.did.resolvers.DidResolverFactory import id.walt.services.ecosystems.cheqd.CheqdService import id.walt.services.ecosystems.iota.IotaService import id.walt.services.ecosystems.iota.IotaWrapper @@ -24,11 +24,6 @@ import id.walt.services.keystore.KeyType import id.walt.services.vc.JsonLdCredentialService import id.walt.signatory.ProofConfig import io.ipfs.multibase.Multibase -import io.ktor.client.* -import io.ktor.client.plugins.* -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.util.* import mu.KotlinLogging import org.bouncycastle.asn1.edec.EdECObjectIdentifiers import org.bouncycastle.asn1.x509.AlgorithmIdentifier @@ -291,12 +286,14 @@ object DidService { //region did-resolve fun resolve(did: String, options: DidOptions? = null): Did = resolve(DidUrl.from(did), options) - fun resolve(didUrl: DidUrl, options: DidOptions? = null): Did = didResolverFactory.create(didUrl.method).resolve(didUrl, options) + fun resolve(didUrl: DidUrl, options: DidOptions? = null): Did = + didResolverFactory.create(didUrl.method).resolve(didUrl, options) //endregion //region did-import fun importDid(did: String) { - val did2 = did.replace("-", ":") + //val did2 = did.replace("-", ":") FIXME + val did2 = did // FIXME resolveAndStore(did2) when { @@ -452,8 +449,10 @@ object DidService { vm.publicKeyBase58 ?: return null - if (!setOf(Ed25519VerificationKey2018.name, Ed25519VerificationKey2019.name, Ed25519VerificationKey2020.name).contains( - vm.type + if (vm.type !in setOf( + Ed25519VerificationKey2018.name, + Ed25519VerificationKey2019.name, + Ed25519VerificationKey2020.name ) ) { log.warn { "Key import does currently not support verification-key algorithm: ${vm.type}" } @@ -478,8 +477,10 @@ object DidService { vm.publicKeyMultibase ?: return null - if (!setOf(Ed25519VerificationKey2018.name, Ed25519VerificationKey2019.name, Ed25519VerificationKey2020.name).contains( - vm.type + if (vm.type !in setOf( + Ed25519VerificationKey2018.name, + Ed25519VerificationKey2019.name, + Ed25519VerificationKey2020.name ) ) { log.warn { "Key import does currently not support verification-key algorithm: ${vm.type}" } @@ -487,10 +488,19 @@ object DidService { return null } + val rawMultibaseDecoded = Multibase.decode(vm.publicKeyMultibase) + + val multibaseDecoded: ByteArray = when { + rawMultibaseDecoded.size == 34 && did.startsWith("did:cheqd:") -> + rawMultibaseDecoded.drop(2).toByteArray() + + else -> rawMultibaseDecoded + } + val keyFactory = KeyFactory.getInstance("Ed25519") - val pubKeyInfo = - SubjectPublicKeyInfo(AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), Multibase.decode(vm.publicKeyMultibase)) + val pubKeyInfo = SubjectPublicKeyInfo(AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), multibaseDecoded) + val x509KeySpec = X509EncodedKeySpec(pubKeyInfo.encoded) val pubKey = keyFactory.generatePublic(x509KeySpec) @@ -528,7 +538,7 @@ object DidService { //endregion fun isDidEbsiV1(did: String): Boolean = checkIsDidEbsiAndVersion(did, 1) - + fun isDidEbsiV2(did: String): Boolean = checkIsDidEbsiAndVersion(did, 2) private fun checkIsDidEbsiAndVersion(did: String, version: Int): Boolean { diff --git a/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt b/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt index 0b31ca3b5..8c3104ea5 100644 --- a/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt +++ b/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt @@ -36,7 +36,9 @@ object CheqdService { private const val verificationMethod = "Ed25519VerificationKey2020" private const val methodSpecificIdAlgo = "uuid" - private const val registrarUrl = "https://registrar.walt.id/cheqd" + + //private const val registrarUrl = "https://registrar.walt.id/cheqd" + private const val registrarUrl = "https://did-registrar.cheqd.net" private const val registrarApiVersion = "1.0" private const val didCreateUrl = "$registrarUrl/$registrarApiVersion/did-document?verificationMethod=%s&methodSpecificIdAlgo=%s&network=%s&publicKeyHex=%s" @@ -73,7 +75,7 @@ object CheqdService { } ?: throw IllegalArgumentException("Failed to fetch the did document from cheqd registrar helper") } - fun deactivateDid(did: String){ + fun deactivateDid(did: String) { val job = initiateDidJob(didCreateUrl, KlaxonWithConverters().toJsonString(JobDeactivateRequest(did))) ?: throw Exception("Failed to initialize the did onboarding process") val signatures = signPayload(KeyId(""), job) @@ -86,11 +88,11 @@ object CheqdService { ?: throw Exception("Failed to finalize the did onboarding process") } - fun updateDid(did: String){ + fun updateDid(did: String) { TODO() } - private fun initiateDidJob(url: String, body: String) = let{ + private fun initiateDidJob(url: String, body: String) = let { val response = runBlocking { client.post(url) { contentType(ContentType.Application.Json) @@ -100,7 +102,7 @@ object CheqdService { KlaxonWithConverters().parse(response) } - private fun finalizeDidJob(url: String, jobId: String, verificationMethodId: String, signatures: List) = let{ + private fun finalizeDidJob(url: String, jobId: String, verificationMethodId: String, signatures: List) = let { val actionResponse = runBlocking { client.post(url) { contentType(ContentType.Application.Json) diff --git a/src/main/kotlin/id/walt/services/hkvstore/FileSystemHKVStore.kt b/src/main/kotlin/id/walt/services/hkvstore/FileSystemHKVStore.kt index 1c33447a3..f8498a282 100644 --- a/src/main/kotlin/id/walt/services/hkvstore/FileSystemHKVStore.kt +++ b/src/main/kotlin/id/walt/services/hkvstore/FileSystemHKVStore.kt @@ -123,7 +123,7 @@ class FileSystemHKVStore(configPath: String) : HKVStoreService() { private fun dataDirCombinePath(key: Path) = configuration.dataDirectory.combineSafe(key) companion object { - private const val MAX_KEY_SIZE = 100 + private const val MAX_KEY_SIZE = 111 private const val hashMappingDesc = "FileSystemHKVStore hash mappings properties" } } diff --git a/src/test/kotlin/id/walt/ecosystems/CheqdTest.kt b/src/test/kotlin/id/walt/ecosystems/CheqdTest.kt new file mode 100644 index 000000000..f25a29690 --- /dev/null +++ b/src/test/kotlin/id/walt/ecosystems/CheqdTest.kt @@ -0,0 +1,55 @@ +package id.walt.ecosystems + +import id.walt.auditor.Auditor +import id.walt.auditor.policies.SignaturePolicy +import id.walt.credentials.w3c.W3CIssuer +import id.walt.model.DidMethod +import id.walt.servicematrix.ServiceMatrix +import id.walt.services.did.DidService +import id.walt.services.keystore.KeyStoreService +import id.walt.signatory.ProofConfig +import id.walt.signatory.Signatory +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe + +class CheqdTest : StringSpec({ + + ServiceMatrix("service-matrix.properties") + + var did: String? = null + + "Generating fresh did:cheqd" { + println("Generating did:cheqd...") + did = DidService.create(DidMethod.cheqd) + println("Created did: $did") + } + + var vc: String? = null + + "Create VC with did:cheqd" { + vc = Signatory.getService().issue("VerifiableId", ProofConfig(did!!, did!!), issuer = W3CIssuer(did!!)) + println("Generated VC: $vc") + } + + "Remove did:cheqd from keystore" { + KeyStoreService.getService().delete(did!!) + println("Deleted: $did") + } + + "Test did:cheqd verification" { + val verificationResult = Auditor.getService().verify(vc!!, listOf(SignaturePolicy())) + + verificationResult.policyResults.entries.forEach { + if (it.value.isFailure) { + println("ERROR at ${it.key}") + it.value.errors.forEachIndexed { index, throwable -> + println("Error #$index: ${throwable.message}") + throwable.printStackTrace() + } + } else println("OK: ${it.key}") + } + verificationResult.result shouldBe true + + } + +})