From 73ec37410700fcb27b70bee6ef585908fcdcd14a Mon Sep 17 00:00:00 2001 From: Kendall Weihe Date: Tue, 30 Jul 2024 17:50:22 -0400 Subject: [PATCH 1/2] Add PortableDid, use existing UniFFI interfaces --- .../sdk/crypto/keys/InMemoryKeyManager.kt | 14 +---------- .../kotlin/web5/sdk/crypto/keys/KeyManager.kt | 21 +--------------- .../kotlin/web5/sdk/crypto/signers/Signer.kt | 21 +--------------- .../main/kotlin/web5/sdk/dids/BearerDid.kt | 20 ++++++++++++--- .../main/kotlin/web5/sdk/dids/PortableDid.kt | 25 +++++++++++++++++++ 5 files changed, 44 insertions(+), 57 deletions(-) create mode 100644 bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt diff --git a/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/InMemoryKeyManager.kt b/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/InMemoryKeyManager.kt index 8de76a03..095f0360 100644 --- a/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/InMemoryKeyManager.kt +++ b/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/InMemoryKeyManager.kt @@ -1,10 +1,8 @@ package web5.sdk.crypto.keys -import web5.sdk.crypto.signers.OuterSigner import web5.sdk.crypto.signers.Signer import web5.sdk.rust.SystemTarget import web5.sdk.rust.InMemoryKeyManager as RustCoreInMemoryKeyManager -import web5.sdk.rust.KeyManager as RustCoreKeyManager /** * A class for managing cryptographic keys in-memory. @@ -34,17 +32,7 @@ class InMemoryKeyManager : KeyManager { * @return Signer The signer for the given public key. */ override fun getSigner(publicJwk: Jwk): Signer { - val innerSigner = this.rustCoreInMemoryKeyManager.getSigner(publicJwk) - return OuterSigner(innerSigner) - } - - /** - * Returns the RustCoreKeyManager. - * - * @return RustCoreKeyManager The rust core key manager. - */ - override fun getRustCoreKeyManager(): RustCoreKeyManager { - return this.rustCoreInMemoryKeyManager.getAsKeyManager() + return this.rustCoreInMemoryKeyManager.getSigner(publicJwk) } /** diff --git a/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/KeyManager.kt b/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/KeyManager.kt index d7fa07d5..d8c82a22 100644 --- a/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/KeyManager.kt +++ b/bound/kt/src/main/kotlin/web5/sdk/crypto/keys/KeyManager.kt @@ -1,25 +1,6 @@ package web5.sdk.crypto.keys -import web5.sdk.crypto.signers.Signer import web5.sdk.rust.KeyManager as RustCoreKeyManager -/** - * An interface representing a key manager for cryptographic operations. - */ -interface KeyManager { +typealias KeyManager = RustCoreKeyManager - /** - * Returns the signer for the given public key. - * - * @param publicKey The public key represented as a Jwk. - * @return Signer The signer for the given public key. - */ - fun getSigner(publicJwk: Jwk): Signer - - /** - * Returns the RustCoreKeyManager - * - * @return RustCoreKeyManager The rust core key manager - */ - fun getRustCoreKeyManager(): RustCoreKeyManager -} diff --git a/bound/kt/src/main/kotlin/web5/sdk/crypto/signers/Signer.kt b/bound/kt/src/main/kotlin/web5/sdk/crypto/signers/Signer.kt index aa241c3b..413a9129 100644 --- a/bound/kt/src/main/kotlin/web5/sdk/crypto/signers/Signer.kt +++ b/bound/kt/src/main/kotlin/web5/sdk/crypto/signers/Signer.kt @@ -1,24 +1,5 @@ package web5.sdk.crypto.signers -import web5.sdk.rust.SystemTarget import web5.sdk.rust.Signer as RustCoreSigner -interface Signer { - fun sign(payload: ByteArray): ByteArray -} - -class OuterSigner: Signer { - init { - SystemTarget.set() // ensure the sys arch is set for first-time loading - } - - private val rustCoreSigner: RustCoreSigner - - constructor(rustCoreSigner: RustCoreSigner) { - this.rustCoreSigner = rustCoreSigner - } - - override fun sign(payload: ByteArray): ByteArray { - return this.rustCoreSigner.sign(payload) - } -} \ No newline at end of file +typealias Signer = RustCoreSigner \ No newline at end of file diff --git a/bound/kt/src/main/kotlin/web5/sdk/dids/BearerDid.kt b/bound/kt/src/main/kotlin/web5/sdk/dids/BearerDid.kt index adf92a29..09928ffc 100644 --- a/bound/kt/src/main/kotlin/web5/sdk/dids/BearerDid.kt +++ b/bound/kt/src/main/kotlin/web5/sdk/dids/BearerDid.kt @@ -2,7 +2,6 @@ package web5.sdk.dids import web5.sdk.crypto.signers.Signer import web5.sdk.crypto.keys.KeyManager -import web5.sdk.crypto.signers.OuterSigner import web5.sdk.rust.SystemTarget import web5.sdk.rust.BearerDid as RustCoreBearerDid @@ -32,13 +31,27 @@ class BearerDid { * @param keyManager The key manager to handle keys. */ constructor(uri: String, keyManager: KeyManager) { - this.rustCoreBearerDid = RustCoreBearerDid(uri, keyManager.getRustCoreKeyManager()) + this.rustCoreBearerDid = RustCoreBearerDid(uri, keyManager) this.did = this.rustCoreBearerDid.getData().did this.document = this.rustCoreBearerDid.getData().document this.keyManager = keyManager } + /** + * Constructs a BearerDid instance from a PortableDid. + * + * @param portableDid The PortableDid. + */ + constructor(portableDid: PortableDid) { + this.rustCoreBearerDid = RustCoreBearerDid.fromPortableDid(portableDid.rustCorePortableDid) + + val data = this.rustCoreBearerDid.getData() + this.did = data.did + this.document = data.document + this.keyManager = data.keyManager + } + /** * Returns a signer for the DID. * @@ -46,7 +59,6 @@ class BearerDid { */ fun getSigner(): Signer { val keyId = this.document.verificationMethod.first().id - val innerSigner = this.rustCoreBearerDid.getSigner(keyId) - return OuterSigner(innerSigner) + return this.rustCoreBearerDid.getSigner(keyId) } } diff --git a/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt b/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt new file mode 100644 index 00000000..b3a98daa --- /dev/null +++ b/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt @@ -0,0 +1,25 @@ +package web5.sdk.dids + +import web5.sdk.crypto.keys.Jwk +import web5.sdk.rust.SystemTarget +import web5.sdk.rust.PortableDid as RustCorePortableDid + +class PortableDid { + init { + SystemTarget.set() // ensure the sys arch is set for first-time loading + } + + val didUri: String + val document: Document + val privateKeys: List + + internal val rustCorePortableDid: RustCorePortableDid + + constructor(json: String) { + this.rustCorePortableDid = RustCorePortableDid(json) + + this.didUri = rustCorePortableDid.getData().didUri + this.document = rustCorePortableDid.getData().document + this.privateKeys = rustCorePortableDid.getData().privateJwks + } +} \ No newline at end of file From 61fbf2828a6861908af82b48b0e8bb482f00ec84 Mon Sep 17 00:00:00 2001 From: Kendall Weihe Date: Wed, 31 Jul 2024 14:32:46 -0400 Subject: [PATCH 2/2] Add PortableDid doc comment, add unit tests --- .../main/kotlin/web5/sdk/dids/PortableDid.kt | 5 ++++ .../kotlin/web5/sdk/dids/PortableDidTest.kt | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 bound/kt/src/test/kotlin/web5/sdk/dids/PortableDidTest.kt diff --git a/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt b/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt index b3a98daa..bc28c1eb 100644 --- a/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt +++ b/bound/kt/src/main/kotlin/web5/sdk/dids/PortableDid.kt @@ -15,6 +15,11 @@ class PortableDid { internal val rustCorePortableDid: RustCorePortableDid + /** + * Constructs a PortableDid from a JSON string. + * + * @param json The JSON string. + */ constructor(json: String) { this.rustCorePortableDid = RustCorePortableDid(json) diff --git a/bound/kt/src/test/kotlin/web5/sdk/dids/PortableDidTest.kt b/bound/kt/src/test/kotlin/web5/sdk/dids/PortableDidTest.kt new file mode 100644 index 00000000..e5753784 --- /dev/null +++ b/bound/kt/src/test/kotlin/web5/sdk/dids/PortableDidTest.kt @@ -0,0 +1,29 @@ +package web5.sdk.dids + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.assertDoesNotThrow +import org.junit.jupiter.api.Assertions.assertThrows +import org.junit.jupiter.api.Assertions.assertEquals +import web5.sdk.rust.RustCoreException + +class PortableDidTest { + @Test + fun `can instantiate from json string`() { + val jsonString = """ + {"uri":"did:web:tbd.website%3A9002:alice","document":{"id":"did:web:tbd.website%3A9002:alice","@context":["https://www.w3.org/ns/did/v1"],"verificationMethod":[{"id":"did:web:tbd.website%3A9002:alice#key-0","type":"JsonWebKey","controller":"did:web:tbd.website%3A9002:alice","publicKeyJwk":{"alg":"Ed25519","kty":"OKP","crv":"Ed25519","x":"NNoVSv_v34ombmylF572t9HYYDiJtMgfckRT1W0vW0g"}}]},"privateKeys":[{"alg":"Ed25519","kty":"OKP","crv":"Ed25519","d":"SwuWbL-Fm64OUFy6x3FBt3RiB79RcnZZrllGT24m4BA","x":"NNoVSv_v34ombmylF572t9HYYDiJtMgfckRT1W0vW0g"}]} + """.trimIndent() + + assertDoesNotThrow { + val portableDid = PortableDid(jsonString) + assertEquals("did:web:tbd.website%3A9002:alice", portableDid.didUri) + } + } + + @Test + fun `instantiation from json string throws with invalid json string`() { + val invalidJsonString = "something not valid" + assertThrows(RustCoreException::class.java) { + PortableDid(invalidJsonString) + } + } +} \ No newline at end of file