Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add full DidJwk & bind to kt #305

Merged
merged 7 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions bindings/web5_uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use web5_uniffi_wrapper::{
did::Did,
methods::{
did_dht::{did_dht_resolve, DidDht},
did_jwk::{did_jwk_resolve, DidJwk},
did_jwk::{did_jwk_create, did_jwk_resolve, DidJwkCreateOptions},
did_web::{did_web_resolve, DidWeb},
},
portable_did::PortableDid,
Expand All @@ -36,10 +36,7 @@ use web5::{
verification_method::VerificationMethod as VerificationMethodData,
},
did::Did as DidData,
methods::{
did_dht::DidDht as DidDhtData, did_jwk::DidJwk as DidJwkData,
did_web::DidWeb as DidWebData,
},
methods::{did_dht::DidDht as DidDhtData, did_web::DidWeb as DidWebData},
portable_did::PortableDid as PortableDidData,
resolution::{
document_metadata::DocumentMetadata as DocumentMetadataData,
Expand Down
26 changes: 12 additions & 14 deletions bindings/web5_uniffi/src/web5.udl
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace web5 {
JwkData ed25519_generator_generate();

[Throws=Web5Error]
BearerDid did_jwk_create(DidJwkCreateOptions? options);
ResolutionResult did_jwk_resolve([ByRef] string uri);

[Async, Throws=Web5Error]
ResolutionResult did_web_resolve([ByRef] string uri);
[Throws=Web5Error]
Expand Down Expand Up @@ -31,21 +34,24 @@ interface Jwk {

[Trait, WithForeign]
interface KeyManager {
[Throws=Web5Error]
JwkData import_private_jwk(JwkData private_jwk);
[Throws=Web5Error]
Signer get_signer(JwkData public_jwk);
};

interface InMemoryKeyManager {
constructor();
[Throws=Web5Error]
Signer get_signer(JwkData public_jwk);
JwkData import_private_jwk(JwkData private_jwk);
[Throws=Web5Error]
JwkData import_private_jwk(JwkData private_key);
Signer get_signer(JwkData public_jwk);
KeyManager get_as_key_manager();
};

enum Dsa {
"Ed25519"
"Ed25519",
"Secp256k1"
};

[Trait, WithForeign]
Expand Down Expand Up @@ -158,17 +164,9 @@ interface ResolutionResult {
ResolutionResultData get_data();
};

dictionary DidJwkData {
DidData did;
DocumentData document;
};

interface DidJwk {
[Name=from_public_jwk, Throws=Web5Error]
constructor(JwkData public_jwk);
[Name=from_uri, Throws=Web5Error]
constructor([ByRef] string uri);
DidJwkData get_data();
dictionary DidJwkCreateOptions {
KeyManager? key_manager;
Dsa? dsa;
};

dictionary DidWebData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use web5::crypto::{
jwk::Jwk,
key_managers::{
in_memory_key_manager::InMemoryKeyManager as InnerInMemoryKeyManager,
key_manager::KeyManager as InnerKeyManager,
KeyManager as InnerKeyManager,
},
};

Expand All @@ -30,6 +30,10 @@ impl InMemoryKeyManager {
}

impl KeyManager for InMemoryKeyManager {
fn import_private_jwk(&self, private_jwk: Jwk) -> Result<Jwk> {
Ok(self.0.import_private_jwk(private_jwk)?)
}

fn get_signer(&self, public_jwk: Jwk) -> Result<Arc<dyn Signer>> {
let signer = self.0.get_signer(public_jwk)?;
let outer_signer = ToOuterSigner(signer);
Expand Down
11 changes: 10 additions & 1 deletion bindings/web5_uniffi_wrapper/src/crypto/key_manager.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
use super::dsa::{Signer, ToInnerSigner, ToOuterSigner};
use crate::errors::Result;
use std::sync::Arc;
use web5::crypto::{jwk::Jwk, key_managers::key_manager::KeyManager as InnerKeyManager};
use web5::crypto::{jwk::Jwk, key_managers::KeyManager as InnerKeyManager};

pub trait KeyManager: Send + Sync {
fn import_private_jwk(&self, private_jwk: Jwk) -> Result<Jwk>;
fn get_signer(&self, public_jwk: Jwk) -> Result<Arc<dyn Signer>>;
}

pub struct ToOuterKeyManager(pub Arc<dyn InnerKeyManager>);

impl KeyManager for ToOuterKeyManager {
fn import_private_jwk(&self, private_jwk: Jwk) -> Result<Jwk> {
Ok(self.0.import_private_jwk(private_jwk)?)
}

fn get_signer(&self, public_jwk: Jwk) -> Result<Arc<dyn Signer>> {
let signer = self.0.get_signer(public_jwk)?;
let outer_signer = ToOuterSigner(signer);
Expand All @@ -20,6 +25,10 @@ impl KeyManager for ToOuterKeyManager {
pub struct ToInnerKeyManager(pub Arc<dyn KeyManager>);

impl InnerKeyManager for ToInnerKeyManager {
fn import_private_jwk(&self, private_jwk: Jwk) -> web5::errors::Result<Jwk> {
Ok(self.0.import_private_jwk(private_jwk)?)
}

fn get_signer(
&self,
public_jwk: Jwk,
Expand Down
41 changes: 27 additions & 14 deletions bindings/web5_uniffi_wrapper/src/dids/methods/did_jwk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
use crate::{dids::resolution::resolution_result::ResolutionResult, errors::Result};
use crate::{
crypto::key_manager::{KeyManager, ToInnerKeyManager},
dids::{bearer_did::BearerDid, resolution::resolution_result::ResolutionResult},
errors::Result,
};
use std::sync::Arc;
use web5::{crypto::jwk::Jwk, dids::methods::did_jwk::DidJwk as InnerDidJwk};
use web5::{
crypto::dsa::Dsa,
dids::methods::did_jwk::{DidJwkCreateOptions as InnerCreateOptions, DidJwk as InnerDidJwk},
};

pub struct DidJwk(pub InnerDidJwk);

Expand All @@ -9,18 +16,24 @@ pub fn did_jwk_resolve(uri: &str) -> Arc<ResolutionResult> {
Arc::new(ResolutionResult(resolution_result))
}

impl DidJwk {
pub fn from_public_jwk(public_key: Jwk) -> Result<Self> {
let did_jwk = InnerDidJwk::from_public_jwk(public_key)?;
Ok(Self(did_jwk))
}
#[derive(Default)]
pub struct DidJwkCreateOptions {
pub key_manager: Option<Arc<dyn KeyManager>>,
pub dsa: Option<Dsa>,
}

pub fn from_uri(uri: &str) -> Result<Self> {
let did_jwk = InnerDidJwk::from_uri(uri)?;
Ok(Self(did_jwk))
}
pub fn did_jwk_create(options: Option<DidJwkCreateOptions>) -> Result<Arc<BearerDid>> {
let inner_options = match options {
None => None,
KendallWeihe marked this conversation as resolved.
Show resolved Hide resolved
Some(options) => Some(InnerCreateOptions {
dsa: options.dsa,
key_manager: match options.key_manager {
None => None,
Some(km) => Some(Arc::new(ToInnerKeyManager(km))),
},
}),
};

pub fn get_data(&self) -> InnerDidJwk {
self.0.clone()
}
let inner_bearer_did = InnerDidJwk::create(inner_options)?;
Ok(Arc::new(BearerDid(inner_bearer_did)))
}
22 changes: 11 additions & 11 deletions bound/kt/src/main/kotlin/web5/sdk/crypto/keys/InMemoryKeyManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ class InMemoryKeyManager (privateJwks: List<Jwk>) : KeyManager {
}
}

/**
* Imports a private key which may be stored somewhere such as environment variables.
*
* @param privateJwk The private key represented as a JWK.
* @return Jwk The public key represented as a JWK.
*/
override fun importPrivateJwk(privateJwk: Jwk): Jwk {
val rustCoreJwkData = this.rustCoreInMemoryKeyManager.importPrivateJwk(privateJwk.rustCoreJwkData)
return Jwk.fromRustCoreJwkData(rustCoreJwkData)
}

/**
* Returns the Signer for the given public key.
*
Expand All @@ -28,15 +39,4 @@ class InMemoryKeyManager (privateJwks: List<Jwk>) : KeyManager {
val rustCoreSigner = this.rustCoreInMemoryKeyManager.getSigner(publicJwk.rustCoreJwkData)
return ToOuterSigner(rustCoreSigner)
}

/**
* Imports a private key which may be stored somewhere such as environment variables.
*
* @param privateJwk The private key represented as a JWK.
* @return Jwk The public key represented as a JWK.
*/
fun importPrivateJwk(privateJwk: Jwk): Jwk {
val rustCoreJwkData = this.rustCoreInMemoryKeyManager.importPrivateJwk(privateJwk.rustCoreJwkData)
return Jwk.fromRustCoreJwkData(rustCoreJwkData)
}
}
13 changes: 13 additions & 0 deletions bound/kt/src/main/kotlin/web5/sdk/crypto/keys/KeyManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,35 @@ package web5.sdk.crypto.keys
import web5.sdk.crypto.signers.ToOuterSigner
import web5.sdk.crypto.signers.Signer
import web5.sdk.crypto.signers.ToInnerSigner
import web5.sdk.rust.JwkData
import web5.sdk.rust.JwkData as RustCoreJwkData
import web5.sdk.rust.KeyManager as RustCoreKeyManager
import web5.sdk.rust.Signer as RustCoreSigner

interface KeyManager {
fun importPrivateJwk(privateJwk: Jwk): Jwk
fun getSigner(publicJwk: Jwk): Signer
}

internal class ToOuterKeyManager(private val rustCoreKeyManager: RustCoreKeyManager) : KeyManager {
override fun importPrivateJwk(privateJwk: Jwk): Jwk {
val rustCoreJwkData = rustCoreKeyManager.importPrivateJwk(privateJwk.rustCoreJwkData)
return Jwk.fromRustCoreJwkData(rustCoreJwkData)
}

override fun getSigner(publicJwk: Jwk): Signer {
val rustCoreSigner = rustCoreKeyManager.getSigner(publicJwk.rustCoreJwkData)
return ToOuterSigner(rustCoreSigner)
}
}

internal class ToInnerKeyManager(private val keyManager: KeyManager) : RustCoreKeyManager {
override fun importPrivateJwk(privateJwk: JwkData): JwkData {
val rustCoreJwkData = Jwk.fromRustCoreJwkData(privateJwk)
val jwk = keyManager.importPrivateJwk(rustCoreJwkData)
return jwk.rustCoreJwkData
}

override fun getSigner(publicJwk: RustCoreJwkData): RustCoreSigner {
val jwk = Jwk.fromRustCoreJwkData(publicJwk)
val signer = keyManager.getSigner(jwk)
Expand Down
61 changes: 30 additions & 31 deletions bound/kt/src/main/kotlin/web5/sdk/dids/methods/jwk/DidJwk.kt
Original file line number Diff line number Diff line change
@@ -1,47 +1,46 @@
package web5.sdk.dids.methods.jwk

import web5.sdk.crypto.keys.Jwk
import web5.sdk.crypto.keys.KeyManager
import web5.sdk.crypto.keys.ToInnerKeyManager
import web5.sdk.crypto.keys.ToOuterKeyManager
import web5.sdk.dids.BearerDid
import web5.sdk.dids.Did
import web5.sdk.dids.Document
import web5.sdk.dids.ResolutionResult
import web5.sdk.rust.Dsa
import web5.sdk.rust.didJwkCreate
import web5.sdk.rust.didJwkCreate as rustCoreJwkCreate
import web5.sdk.rust.DidJwkCreateOptions as RustCoreDidJwkCreateOptions
import web5.sdk.rust.didJwkResolve as rustCoreDidJwkResolve
import web5.sdk.rust.DidJwk as RustCoreDidJwk

data class DidJwkCreateOptions(
val keyManager: KeyManager? = null,
val dsa: Dsa? = null
KendallWeihe marked this conversation as resolved.
Show resolved Hide resolved
)

/**
* A class representing a DID (Decentralized Identifier) using the JWK (JSON Web Key) method.
*
* @property did The DID associated with this instance.
* @property document The DID document associated with this instance.
*/
class DidJwk {
val did: Did
val document: Document

/**
* Constructs a DidJwk instance using a public key.
*
* @param publicKey The public key represented as a Jwk.
*/
constructor(publicKey: Jwk) {
val rustCoreDidJwk = RustCoreDidJwk.fromPublicJwk(publicKey.rustCoreJwkData)

this.did = Did.fromRustCoreDidData(rustCoreDidJwk.getData().did)
this.document = rustCoreDidJwk.getData().document
}

/**
* Constructs a DidJwk instance using a DID URI.
*
* @param uri The DID URI.
*/
constructor(uri: String) {
val rustCoreDidJwk = RustCoreDidJwk.fromUri(uri)

this.did = Did.fromRustCoreDidData(rustCoreDidJwk.getData().did)
this.document = rustCoreDidJwk.getData().document
}

companion object {
/**
* Create a DidJwk BearerDid using available options.
*
* @param options The set of options to configure creation.
*/
fun create(options: DidJwkCreateOptions? = null): BearerDid {
val rustCoreOptions = options?.let { opts ->
RustCoreDidJwkCreateOptions(
keyManager = opts.keyManager?.let { ToInnerKeyManager(it) },
dsa = opts.dsa
) }
val rustCoreBearerDid = didJwkCreate(rustCoreOptions)
val rustCoreBearerDidData = rustCoreBearerDid.getData()
val keyManager = ToOuterKeyManager(rustCoreBearerDidData.keyManager)
return BearerDid(rustCoreBearerDidData.did.uri, keyManager)
}

/**
* Resolves a DID URI to a DidResolutionResult.
*
Expand Down
Loading
Loading