Skip to content

Commit

Permalink
Add feature complete Jwk (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
KendallWeihe authored Aug 20, 2024
1 parent 904cfe2 commit 6944830
Show file tree
Hide file tree
Showing 40 changed files with 894 additions and 188 deletions.
1 change: 1 addition & 0 deletions bindings/web5_uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use web5_uniffi_wrapper::{
Signer, Verifier,
},
in_memory_key_manager::InMemoryKeyManager,
jwk::Jwk,
key_manager::KeyManager,
},
dids::{
Expand Down
13 changes: 10 additions & 3 deletions bindings/web5_uniffi/src/web5.udl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ dictionary JwkData {
string? y;
};

interface Jwk {
constructor(JwkData data);
JwkData get_data();
[Throws=Web5Error]
string compute_thumbprint();
};

[Trait, WithForeign]
interface KeyManager {
[Throws=Web5Error]
Expand Down Expand Up @@ -112,8 +119,6 @@ dictionary ServiceData {
interface Document {
constructor(DocumentData data);
DocumentData get_data();
[Throws=Web5Error]
JwkData find_public_key_jwk(string key_id);
};

enum ResolutionMetadataError {
Expand Down Expand Up @@ -203,9 +208,11 @@ dictionary PortableDidData {
};

interface PortableDid {
[Throws=Web5Error]
[Name=from_json_string, Throws=Web5Error]
constructor([ByRef] string json);
PortableDidData get_data();
[Throws=Web5Error]
string to_json_string();
};

dictionary BearerDidData {
Expand Down
19 changes: 19 additions & 0 deletions bindings/web5_uniffi_wrapper/src/crypto/jwk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::errors::Result;
use web5::crypto::jwk::Jwk as InnerJwk;

pub struct Jwk(pub InnerJwk);

impl Jwk {
pub fn new(data: InnerJwk) -> Self {
Self(data)
}

pub fn get_data(&self) -> InnerJwk {
self.0.clone()
}

pub fn compute_thumbprint(&self) -> Result<String> {
let thumbprint = self.0.compute_thumbprint()?;
Ok(thumbprint)
}
}
1 change: 1 addition & 0 deletions bindings/web5_uniffi_wrapper/src/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod dsa;

pub mod in_memory_key_manager;
pub mod jwk;
pub mod key_manager;
7 changes: 1 addition & 6 deletions bindings/web5_uniffi_wrapper/src/dids/data_model/document.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::errors::Result;
use web5::{crypto::jwk::Jwk, dids::data_model::document::Document as InnerDocument};
use web5::dids::data_model::document::Document as InnerDocument;

pub struct Document(pub InnerDocument);

Expand All @@ -11,8 +10,4 @@ impl Document {
pub fn get_data(&self) -> InnerDocument {
self.0.clone()
}

pub fn find_public_key_jwk(&self, key_id: String) -> Result<Jwk> {
Ok(self.0.find_public_key_jwk(key_id)?)
}
}
15 changes: 11 additions & 4 deletions bindings/web5_uniffi_wrapper/src/dids/portable_did.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
use web5::dids::portable_did::PortableDid as InnerPortableDid;

use crate::errors::Result;
use web5::{
dids::portable_did::PortableDid as InnerPortableDid,
json::{FromJson, ToJson},
};

pub struct PortableDid(pub InnerPortableDid);

impl PortableDid {
pub fn new(json: &str) -> Result<Self> {
let inner_portable_did = InnerPortableDid::new(json)?;
pub fn from_json_string(json: &str) -> Result<Self> {
let inner_portable_did = InnerPortableDid::from_json_string(json)?;
Ok(Self(inner_portable_did))
}

pub fn get_data(&self) -> InnerPortableDid {
self.0.clone()
}

pub fn to_json_string(&self) -> Result<String> {
let json_string = self.0.to_json_string()?;
Ok(json_string)
}
}
30 changes: 2 additions & 28 deletions bindings/web5_uniffi_wrapper/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ use thiserror::Error;
use web5::credentials::presentation_definition::PexError;
use web5::credentials::CredentialError;
use web5::crypto::dsa::DsaError;
use web5::crypto::{jwk::JwkError, key_managers::KeyManagerError};
use web5::crypto::key_managers::KeyManagerError;
use web5::dids::bearer_did::BearerDidError;
use web5::dids::data_model::DataModelError as DidDataModelError;
use web5::dids::methods::MethodError;
use web5::dids::portable_did::PortableDidError;
use web5::errors::Web5Error as InnerWeb5Error;

#[derive(Debug, Error)]
Expand Down Expand Up @@ -79,12 +77,6 @@ where
variant_name.to_string()
}

impl From<JwkError> for Web5Error {
fn from(error: JwkError) -> Self {
Web5Error::new(error)
}
}

impl From<KeyManagerError> for Web5Error {
fn from(error: KeyManagerError) -> Self {
Web5Error::new(error)
Expand All @@ -97,12 +89,6 @@ impl From<DsaError> for Web5Error {
}
}

impl From<PortableDidError> for Web5Error {
fn from(error: PortableDidError) -> Self {
Web5Error::new(error)
}
}

impl From<MethodError> for Web5Error {
fn from(error: MethodError) -> Self {
Web5Error::new(error)
Expand All @@ -121,12 +107,6 @@ impl From<PexError> for Web5Error {
}
}

impl From<DidDataModelError> for Web5Error {
fn from(error: DidDataModelError) -> Self {
Web5Error::new(error)
}
}

impl From<BearerDidError> for Web5Error {
fn from(error: BearerDidError) -> Self {
Web5Error::new(error)
Expand All @@ -144,13 +124,7 @@ impl From<Web5Error> for KeyManagerError {
let variant = error.variant();
let msg = error.msg();

if variant
== variant_name(&KeyManagerError::JwkError(JwkError::ThumbprintFailed(
String::default(),
)))
{
return KeyManagerError::JwkError(JwkError::ThumbprintFailed(msg.to_string()));
} else if variant == variant_name(&KeyManagerError::KeyGenerationFailed) {
if variant == variant_name(&KeyManagerError::KeyGenerationFailed) {
return KeyManagerError::KeyGenerationFailed;
} else if variant
== variant_name(&KeyManagerError::InternalKeyStoreError(String::default()))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package web5.sdk.crypto.keys

import web5.sdk.crypto.signers.ToOuterSigner
import web5.sdk.crypto.signers.Signer
import web5.sdk.rust.InMemoryKeyManager as RustCoreInMemoryKeyManager

Expand All @@ -16,7 +17,7 @@ class InMemoryKeyManager : KeyManager {
*/
constructor(privateJwks: List<Jwk>) {
privateJwks.forEach {
this.rustCoreInMemoryKeyManager.importPrivateJwk(it)
this.rustCoreInMemoryKeyManager.importPrivateJwk(it.rustCoreJwkData)
}
}

Expand All @@ -27,7 +28,8 @@ class InMemoryKeyManager : KeyManager {
* @return Signer The signer for the given public key.
*/
override fun getSigner(publicJwk: Jwk): Signer {
return this.rustCoreInMemoryKeyManager.getSigner(publicJwk)
val rustCoreSigner = this.rustCoreInMemoryKeyManager.getSigner(publicJwk.rustCoreJwkData)
return ToOuterSigner(rustCoreSigner)
}

/**
Expand All @@ -37,6 +39,7 @@ class InMemoryKeyManager : KeyManager {
* @return Jwk The public key represented as a JWK.
*/
fun importPrivateJwk(privateJwk: Jwk): Jwk {
return this.rustCoreInMemoryKeyManager.importPrivateJwk(privateJwk)
val rustCoreJwkData = this.rustCoreInMemoryKeyManager.importPrivateJwk(privateJwk.rustCoreJwkData)
return Jwk.fromRustCoreJwkData(rustCoreJwkData)
}
}
36 changes: 35 additions & 1 deletion bound/kt/src/main/kotlin/web5/sdk/crypto/keys/Jwk.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,44 @@
package web5.sdk.crypto.keys

import web5.sdk.rust.Jwk as RustCoreJwk
import web5.sdk.rust.JwkData as RustCoreJwkData

/**
* Partial representation of a [JSON Web Key as per RFC7517](https://tools.ietf.org/html/rfc7517).
* Note that this is a subset of the spec.
*/
data class Jwk (
val alg: String? = null,
val kty: String,
val crv: String,
val x: String,
val y: String? = null,
val d: String? = null
) {
internal val rustCoreJwkData: RustCoreJwkData = RustCoreJwkData(
alg,
kty,
crv,
d,
x,
y
)

typealias Jwk = RustCoreJwkData
internal companion object {
fun fromRustCoreJwkData(rustCoreJwkData: RustCoreJwkData): Jwk {
return Jwk(
rustCoreJwkData.alg,
rustCoreJwkData.kty,
rustCoreJwkData.crv,
rustCoreJwkData.x,
rustCoreJwkData.y,
rustCoreJwkData.d,
)
}
}

fun computeThumbprint(): String {
val rustCoreJwk = RustCoreJwk(rustCoreJwkData)
return rustCoreJwk.computeThumbprint()
}
}
24 changes: 23 additions & 1 deletion bound/kt/src/main/kotlin/web5/sdk/crypto/keys/KeyManager.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
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 as RustCoreJwkData
import web5.sdk.rust.KeyManager as RustCoreKeyManager
import web5.sdk.rust.Signer as RustCoreSigner

typealias KeyManager = RustCoreKeyManager
interface KeyManager {
fun getSigner(publicJwk: Jwk): Signer
}

internal class ToOuterKeyManager(private val rustCoreKeyManager: RustCoreKeyManager) : KeyManager {
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 getSigner(publicJwk: RustCoreJwkData): RustCoreSigner {
val jwk = Jwk.fromRustCoreJwkData(publicJwk)
val signer = keyManager.getSigner(jwk)
val innerSigner = ToInnerSigner(signer)
return innerSigner
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Ed25519Signer : Signer {
private val rustCoreSigner: RustCoreEd25519Signer

constructor(privateKey: Jwk) {
this.rustCoreSigner = RustCoreEd25519Signer(privateKey)
this.rustCoreSigner = RustCoreEd25519Signer(privateKey.rustCoreJwkData)
}

private constructor(rustCoreSigner: RustCoreEd25519Signer) {
Expand Down
16 changes: 15 additions & 1 deletion bound/kt/src/main/kotlin/web5/sdk/crypto/signers/Signer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,18 @@ package web5.sdk.crypto.signers

import web5.sdk.rust.Signer as RustCoreSigner

typealias Signer = RustCoreSigner
interface Signer {
fun sign(payload: ByteArray): ByteArray
}

internal class ToOuterSigner(private val rustCoreSigner: RustCoreSigner) : Signer {
override fun sign(payload: ByteArray): ByteArray {
return rustCoreSigner.sign(payload)
}
}

internal class ToInnerSigner(private val signer: Signer) : RustCoreSigner {
override fun sign(payload: ByteArray): ByteArray {
return signer.sign(payload)
}
}
10 changes: 7 additions & 3 deletions bound/kt/src/main/kotlin/web5/sdk/dids/BearerDid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package web5.sdk.dids

import web5.sdk.crypto.signers.Signer
import web5.sdk.crypto.keys.KeyManager
import web5.sdk.crypto.keys.ToInnerKeyManager
import web5.sdk.crypto.keys.ToOuterKeyManager
import web5.sdk.crypto.signers.ToOuterSigner
import web5.sdk.rust.BearerDid as RustCoreBearerDid

/**
Expand All @@ -25,7 +28,8 @@ class BearerDid {
* @param keyManager The key manager to handle keys.
*/
constructor(uri: String, keyManager: KeyManager) {
this.rustCoreBearerDid = RustCoreBearerDid(uri, keyManager)
val innerKeyManager = ToInnerKeyManager(keyManager)
this.rustCoreBearerDid = RustCoreBearerDid(uri, innerKeyManager)

this.did = Did.fromRustCoreDidData(this.rustCoreBearerDid.getData().did)
this.document = this.rustCoreBearerDid.getData().document
Expand All @@ -43,7 +47,7 @@ class BearerDid {
val data = this.rustCoreBearerDid.getData()
this.did = Did.fromRustCoreDidData(data.did)
this.document = data.document
this.keyManager = data.keyManager
this.keyManager = ToOuterKeyManager(data.keyManager)
}

/**
Expand All @@ -53,6 +57,6 @@ class BearerDid {
*/
fun getSigner(): Signer {
val keyId = this.document.verificationMethod.first().id
return this.rustCoreBearerDid.getSigner(keyId)
return ToOuterSigner(this.rustCoreBearerDid.getSigner(keyId))
}
}
2 changes: 1 addition & 1 deletion bound/kt/src/main/kotlin/web5/sdk/dids/Did.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ data class Did (
fun parse(uri: String): Did {
val rustCoreDid = RustCoreDid(uri)
val data = rustCoreDid.getData()
return Did.fromRustCoreDidData(data)
return fromRustCoreDidData(data)
}

internal fun fromRustCoreDidData(data: RustCoreDidData): Did {
Expand Down
Loading

0 comments on commit 6944830

Please sign in to comment.